最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue AST的轉(zhuǎn)換實(shí)現(xiàn)方法講解

 更新時(shí)間:2023年01月05日 14:02:53   作者:loyd3  
本節(jié),我們將討論關(guān)于AST的轉(zhuǎn)換。所謂AST的轉(zhuǎn)換,指的是對(duì)AST進(jìn)行一系列操作,將其轉(zhuǎn)換為新的AST的過(guò)程。新的AST可以是原語(yǔ)言或原DSL的描述,也可以是其他語(yǔ)言或其他DSL的描述。例如,我們可以對(duì)模板AST進(jìn)行操作,將其轉(zhuǎn)換為JavaScriptAST

本節(jié),我們將討論關(guān)于AST的轉(zhuǎn)換。所謂AST的轉(zhuǎn)換,指的是對(duì)AST進(jìn)行一系列操作,將其轉(zhuǎn)換為新的AST的過(guò)程。新的AST可以是原語(yǔ)言或原DSL的描述,也可以是其他語(yǔ)言或其他DSL的描述。

例如,我們可以對(duì)模板AST進(jìn)行操作,將其轉(zhuǎn)換為JavaScriptAST。轉(zhuǎn)換后的AST可以用于代碼生成。這其實(shí)就是 Vue.js 的模板編譯器將模板編譯為渲染函數(shù)的過(guò)程

transform函數(shù)就是用來(lái)完成AST轉(zhuǎn)換工作的

為了對(duì)AST進(jìn)行轉(zhuǎn)換,我們需要能訪問(wèn)AST 的每一個(gè)節(jié)點(diǎn),這樣才有機(jī)會(huì)對(duì)特定節(jié)點(diǎn)進(jìn)行修改、替換、刪除等操作。

由子AST 是樹型數(shù)據(jù)結(jié)構(gòu),所以我們需要編寫一個(gè)深度優(yōu)先的遍歷算法從而實(shí)現(xiàn)對(duì)AST中節(jié)點(diǎn)的訪回。

在開始編寫轉(zhuǎn)換代碼之前,需要一個(gè)dump工具函數(shù),用來(lái)打印當(dāng)前AST中節(jié)點(diǎn)的信息,如下面代碼所示:

function dump(node, indent = 0) {
	// 節(jié)點(diǎn)的類型
	const type = node.type
	// 節(jié)點(diǎn)的描述,如果是根節(jié)點(diǎn),則沒有描述
	// 如果是Element類型的節(jié)點(diǎn),則使用node.tag作為節(jié)點(diǎn)的描述
	// 如果是Text類型的節(jié)點(diǎn),則使用node.content作為節(jié)點(diǎn)的描述
	const desc = node.type === 'Root'?'':node.type === 'Element'?node.tag:node.content
	// 打印節(jié)點(diǎn)的類型和描述信息
	console.log(`${'-'.repeat(indent)}${type}:${desc}`)
	// 遞歸地打印子節(jié)點(diǎn)
	if(node.children){
		node.children.forEach(n=>demp(n,indent+2))
	}
}

dump 函數(shù)會(huì)輸出怎樣的結(jié)果:

const ast = parse(`<div><p>Vue</p><p>Template</p></div>`)
console.log(dump(ast))

運(yùn)行上面這段代碼,將得到如下輸出:

Root:
--Element: div
----Element: p
------Text: Vue
----Element: p
-----Text: Template

接下來(lái),我們將著手實(shí)現(xiàn)對(duì)AST 中節(jié)點(diǎn)的訪問(wèn)。

代碼如下所示:

function traverseNode(ast){
	const currentNode = ast
	const children = currentNode.children
	if(children){
		for(let i=0,i<children.length;i++){
			traverseNode(children[i])
		}
	}
}

traverseNode 函數(shù)用來(lái)以深度優(yōu)先的方式遍歷 AST,它的實(shí)現(xiàn)與 dump 幾乎相同

有traverseNode 函數(shù)之后,即可實(shí)現(xiàn)對(duì) AST 中節(jié)點(diǎn)的訪問(wèn)。例如,可以實(shí)現(xiàn)一個(gè)轉(zhuǎn)換功能,將AST中所有p標(biāo)簽轉(zhuǎn)換為h1標(biāo)簽,如下面的代碼所示:

function traverseNode(ast){
	// 當(dāng)前節(jié)點(diǎn),ast本身就是Root節(jié)點(diǎn)
	const currentNode = ast
	// 對(duì)當(dāng)前節(jié)點(diǎn)進(jìn)行操作
	if(currentNode.type === 'Element' && currentNode.tag === 'p'){
		currentNode.tag = 'h1'
	}
	// 如果有子節(jié)點(diǎn),則遞歸地調(diào)用traverseNode函數(shù)進(jìn)行遍歷
	// 遞歸調(diào)用
	const children = currentNode.children
	if(children){
		for(let i=0;i<children.length;i++){
			traverseNode(children[i])
		}
	}
}

還可以對(duì)AST進(jìn)行其他轉(zhuǎn)換。例如,實(shí)現(xiàn)一個(gè)轉(zhuǎn)換,將文本節(jié)點(diǎn)的內(nèi)容重復(fù)兩次

function traverseNode(ast){
	const currentNode = ast
	if(currentNode.type === 'Element' && currentNode.tag === 'p'){
		currentNode.tag = 'h1'
	}
	if(currentNode.type === 'Text'){
		currentNode.content = currentNode.content.repeat(2)
	}
	const children = currentNode.children
	if(children){
		for(let i=0;i<children.length;i++){
			traverseNode(children[i])
		}
	}
}

不過(guò),隨著功能的不斷增加,traverseNode 函數(shù)將會(huì)變得越來(lái)越“臃腫”。這時(shí),我們很自然地想到,能否對(duì)節(jié)點(diǎn)的操作和訪問(wèn)進(jìn)行解耦呢? 答案是“當(dāng)然可以”,我們可以使用回調(diào)函數(shù)的機(jī)制來(lái)實(shí)現(xiàn)解耦,如下面代碼所示

// 接收第二個(gè)參數(shù)context
function traverseNode(ast, context){
	const currentNode = ast
	// context.nodeTransforms是一個(gè)數(shù)組,其中每一個(gè)元素都是一個(gè)函數(shù)
	const transforms = context.nodeTransforms
	for(let i = 0;i<transforms.length;i++){
		// 將當(dāng)前節(jié)點(diǎn) currentNode 和 context 都傳遞給 nodeTransforms 中注冊(cè)的回調(diào)函數(shù)
		transforms[i](currentNode,context)
	}
	const children = currentNode.children
	if(children){
		for(let i=0;i<children.length;i++){
			traverseNode(children[i])
		}
	}
}

接著,我們把回調(diào)函數(shù)存儲(chǔ)到context.nodeTransforns 數(shù)組中,然后遍歷該數(shù)組,并逐個(gè)調(diào)用注冊(cè)在其中的回調(diào)函數(shù)。最后,我們將當(dāng)前節(jié)點(diǎn)curentNode和context對(duì)像分別作為參數(shù)傳遞給回調(diào)函數(shù)。

有了修改后的traverseNode函數(shù),就可以這樣使用它了

function transform(ast){
	// 在transform函數(shù)內(nèi)創(chuàng)建context對(duì)象
	const context = {
		//注冊(cè) nodeTransforms 數(shù)組
		nodeTransforms:[
			transformElement, // transformElement 函數(shù)用來(lái)轉(zhuǎn)換標(biāo)簽節(jié)點(diǎn)
			transformText //transformText 函數(shù)用來(lái)轉(zhuǎn)換文本節(jié)點(diǎn)
		]
	}
	//調(diào)用 traverseNode 完成轉(zhuǎn)換
	traverseNode(ast, context)
	console.log(dump(ast))
}

其中transformElement和transformText函數(shù)的實(shí)現(xiàn)如下

function transformElement(node){
	if(node.type === 'Element' && node.tag === 'p'){
		node.tag = 'h1'
	}
}
function transformElement(node){
	if(node.type === 'Text'){
		node.content = node.content.repeat(2)
	}
}

可以看到,解耦之后,節(jié)點(diǎn)操作封裝到了 transformELement和 transformText 這樣的獨(dú)立函數(shù)中。我們甚至可以編寫任意多個(gè)類似的轉(zhuǎn)換函數(shù),只需要將它們注冊(cè)到 context.nodeTransforns中即可。這樣就解決了功能增加所導(dǎo)致的 traverseNode 函數(shù)“臃腫”的問(wèn)題。

到此這篇關(guān)于Vue AST的轉(zhuǎn)換實(shí)現(xiàn)方法講解的文章就介紹到這了,更多相關(guān)Vue AST轉(zhuǎn)換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue插件及修改ip啟動(dòng)端口解析

    vue插件及修改ip啟動(dòng)端口解析

    這篇文章主要為大家介紹了vue插件及修改ip啟動(dòng)端口的解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04
  • VUE利用vuex模擬實(shí)現(xiàn)新聞點(diǎn)贊功能實(shí)例

    VUE利用vuex模擬實(shí)現(xiàn)新聞點(diǎn)贊功能實(shí)例

    本篇文章主要介紹了VUE利用vuex模擬實(shí)現(xiàn)新聞點(diǎn)贊功能實(shí)例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06
  • vue2實(shí)現(xiàn)傳送門效果的示例

    vue2實(shí)現(xiàn)傳送門效果的示例

    本文主要介紹了vue2實(shí)現(xiàn)傳送門效果的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • vue.js事件處理器是什么

    vue.js事件處理器是什么

    什么是vue.js事件處理器?這篇文章主要介紹了vue.js事件處理器的相關(guān)資料
    2017-03-03
  • 在vue中v-bind使用三目運(yùn)算符綁定class的實(shí)例

    在vue中v-bind使用三目運(yùn)算符綁定class的實(shí)例

    今天小編就為大家分享一篇在vue中v-bind使用三目運(yùn)算符綁定class的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-09-09
  • uniapp使用v-loading并且不引入element-ui的操作方法

    uniapp使用v-loading并且不引入element-ui的操作方法

    這篇文章主要介紹了uniapp使用v-loading并且不引入element-ui,首先創(chuàng)建loading.js,創(chuàng)建lloading.scss,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-10-10
  • VUE+Element實(shí)現(xiàn)增刪改查的示例源碼

    VUE+Element實(shí)現(xiàn)增刪改查的示例源碼

    這篇文章主要介紹了VUE+Element實(shí)現(xiàn)增刪改查的示例源碼,幫助大家更好的理解和使用vue,感興趣的朋友可以了解下
    2020-11-11
  • vue項(xiàng)目如何使用$router.go(-1)返回時(shí)刷新原來(lái)的界面

    vue項(xiàng)目如何使用$router.go(-1)返回時(shí)刷新原來(lái)的界面

    這篇文章主要介紹了vue項(xiàng)目如何使用$router.go(-1)返回時(shí)刷新原來(lái)的界面問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • vue項(xiàng)目部署上線遇到的問(wèn)題及解決方法

    vue項(xiàng)目部署上線遇到的問(wèn)題及解決方法

    這篇文章主要介紹了vue項(xiàng)目部署上線遇到的問(wèn)題及解決方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下
    2018-06-06
  • 詳解.vue文件中style標(biāo)簽的幾個(gè)標(biāo)識(shí)符

    詳解.vue文件中style標(biāo)簽的幾個(gè)標(biāo)識(shí)符

    這篇文章主要介紹了詳解.vue文件中style標(biāo)簽的幾個(gè)標(biāo)識(shí)符,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07

最新評(píng)論

建德市| 唐河县| 繁峙县| 尉氏县| 达孜县| 吉木乃县| 阜阳市| 泰宁县| 南溪县| 那坡县| 崇仁县| 西青区| 孝义市| 桃园市| 富源县| 钦州市| 富锦市| 兴义市| 盐城市| 英吉沙县| 剑阁县| 龙川县| 来安县| 开远市| 临高县| 巴里| 泾川县| 福安市| 务川| 天台县| 澳门| 恩施市| 辽源市| 海口市| 阿克陶县| 安溪县| 玉溪市| 吉木萨尔县| 招远市| 托里县| 磐安县|