我的编程空间,编程开发者的网络收藏夹
学习永远不晚

VueAST的转换实现方法讲解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

VueAST的转换实现方法讲解

本节,我们将讨论关于AST的转换。所谓AST的转换,指的是对AST进行一系列操作,将其转换为新的AST的过程。新的AST可以是原语言或原DSL的描述,也可以是其他语言或其他DSL的描述。

例如,我们可以对模板AST进行操作,将其转换为JavaScriptAST。转换后的AST可以用于代码生成。这其实就是 Vue.js 的模板编译器将模板编译为渲染函数的过程

transform函数就是用来完成AST转换工作的

为了对AST进行转换,我们需要能访问AST 的每一个节点,这样才有机会对特定节点进行修改、替换、删除等操作。

由子AST 是树型数据结构,所以我们需要编写一个深度优先的遍历算法从而实现对AST中节点的访回。

在开始编写转换代码之前,需要一个dump工具函数,用来打印当前AST中节点的信息,如下面代码所示:

function dump(node, indent = 0) {
	// 节点的类型
	const type = node.type
	// 节点的描述,如果是根节点,则没有描述
	// 如果是Element类型的节点,则使用node.tag作为节点的描述
	// 如果是Text类型的节点,则使用node.content作为节点的描述
	const desc = node.type === 'Root'?'':node.type === 'Element'?node.tag:node.content
	// 打印节点的类型和描述信息
	console.log(`${'-'.repeat(indent)}${type}:${desc}`)
	// 递归地打印子节点
	if(node.children){
		node.children.forEach(n=>demp(n,indent+2))
	}
}

dump 函数会输出怎样的结果:

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

运行上面这段代码,将得到如下输出:

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

接下来,我们将着手实现对AST 中节点的访问。

代码如下所示:

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

traverseNode 函数用来以深度优先的方式遍历 AST,它的实现与 dump 几乎相同

有traverseNode 函数之后,即可实现对 AST 中节点的访问。例如,可以实现一个转换功能,将AST中所有p标签转换为h1标签,如下面的代码所示:

function traverseNode(ast){
	// 当前节点,ast本身就是Root节点
	const currentNode = ast
	// 对当前节点进行操作
	if(currentNode.type === 'Element' && currentNode.tag === 'p'){
		currentNode.tag = 'h1'
	}
	// 如果有子节点,则递归地调用traverseNode函数进行遍历
	// 递归调用
	const children = currentNode.children
	if(children){
		for(let i=0;i<children.length;i++){
			traverseNode(children[i])
		}
	}
}

还可以对AST进行其他转换。例如,实现一个转换,将文本节点的内容重复两次

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])
		}
	}
}

不过,随着功能的不断增加,traverseNode 函数将会变得越来越“臃肿”。这时,我们很自然地想到,能否对节点的操作和访问进行解耦呢? 答案是“当然可以”,我们可以使用回调函数的机制来实现解耦,如下面代码所示

// 接收第二个参数context
function traverseNode(ast, context){
	const currentNode = ast
	// context.nodeTransforms是一个数组,其中每一个元素都是一个函数
	const transforms = context.nodeTransforms
	for(let i = 0;i<transforms.length;i++){
		// 将当前节点 currentNode 和 context 都传递给 nodeTransforms 中注册的回调函数
		transforms[i](currentNode,context)
	}
	const children = currentNode.children
	if(children){
		for(let i=0;i<children.length;i++){
			traverseNode(children[i])
		}
	}
}

接着,我们把回调函数存储到context.nodeTransforns 数组中,然后遍历该数组,并逐个调用注册在其中的回调函数。最后,我们将当前节点curentNode和context对像分别作为参数传递给回调函数。

有了修改后的traverseNode函数,就可以这样使用它了

function transform(ast){
	// 在transform函数内创建context对象
	const context = {
		//注册 nodeTransforms 数组
		nodeTransforms:[
			transformElement, // transformElement 函数用来转换标签节点
			transformText //transformText 函数用来转换文本节点
		]
	}
	//调用 traverseNode 完成转换
	traverseNode(ast, context)
	console.log(dump(ast))
}

其中transformElement和transformText函数的实现如下

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)
	}
}

可以看到,解耦之后,节点操作封装到了 transformELement和 transformText 这样的独立函数中。我们甚至可以编写任意多个类似的转换函数,只需要将它们注册到 context.nodeTransforns中即可。这样就解决了功能增加所导致的 traverseNode 函数“臃肿”的问题。

到此这篇关于Vue AST的转换实现方法讲解的文章就介绍到这了,更多相关Vue AST转换内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

VueAST的转换实现方法讲解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

VueAST的转换实现方法讲解

本节,我们将讨论关于AST的转换。所谓AST的转换,指的是对AST进行一系列操作,将其转换为新的AST的过程。新的AST可以是原语言或原DSL的描述,也可以是其他语言或其他DSL的描述。例如,我们可以对模板AST进行操作,将其转换为JavaScriptAST
2023-01-05

C#实现Word转换TXT的方法详解

这篇文章主要为大家详细介绍了如何利用C#实现Word转换TXT的功能,文中的示例代码讲解详细,对我们学习C#有一定的帮助,感兴趣的小伙伴可以跟随小编一起了解一下
2022-12-22

mybatis中实现枚举自动转换方法详解

前言最近在工作中遇到一个问题,在设计数据库的时候,我们有时候会把表里的某个字段的值设置为数字或者为英文来表示他的一些特殊含义。就拿设置成数字来说,假如1对应是学生,2对应是教师,在Java里面定义成这样的枚举,但是一般使用mybatis查出
2023-05-31

Golang泛型实现类型转换的方法实例

将一个值从一种类型转换到另一种类型,便发生了类型转换,下面这篇文章主要给大家介绍了关于Golang泛型实现类型转换的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
2022-12-30

Python数据类型转换实现方法

这篇文章主要介绍了Python数据类型转换的实现,有时候,我们需要对数据内置的类型进行转换,数据类型的转换,一般情况下你只需要将数据类型作为函数名即可
2022-12-08

python实现中文转换url编码的方法

本文实例讲述了python实现中文转换url编码的方法。分享给大家供大家参考,具体如下: 今天要处理百度贴吧的东西。想要做一个关键词的list,每次需要时,直接添加 到list里面就可以了。但是添加到list里面是中文的情况(比如‘丽江')
2022-06-04

Vue使用Less与Scss实现主题切换方法详细讲解

目前,在众多的后台管理系统中,换肤功能已是一个很常见的功能。用户可以根据自己的喜好,设置页面的主题,从而实现个性化定制。目前,我所了解到的换肤方式,也是我目前所掌握的两种换肤方式,想同大家一起分享
2023-02-25

Java图片与二进制相互转换实现示例讲解

这篇文章主要介绍了Java图片与二进制相互转换实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
2023-03-19

Android中URL转换成二维码的实现方法

这篇文章主要讲解了Android中URL转换成二维码的实现方法,内容清晰明了,对此有兴趣的小伙伴可以学习一下,相信大家阅读完之后会有帮助。二维码已经成为我们日常生活中的一个不可获取的产物,火车票上,景区门票,超市付款等等都会有二维码的身影。
2023-05-31

编程热搜

目录