VUE:简易解析器实现
创始人
2024-01-17 21:00:15
0

VUE中的模板编译是把模板通过模板编译器生成渲染函数的过程。
模板编译分为三个步骤

  1. 将模板解析成AST
  2. 遍历AST标记静态节点
  3. 将AST生成渲染函数

这三个部分分别由解析器、优化器、生成器实现。
本文主要介绍解析器,如何将模板解析,然后替换,再输出到页面上。

Compiler构造函数,用于获取指定元素的内容,并进行解析,根据内容的不同使用不同的函数进行处理。
根据node.nodeType判断节点的类型,然后使用对应的解析方法进行解析,将解析后的结果给元素赋值。
对于元素节点使用compileNode处理,对于文本节点使用compileText处理。

compileNode()方法读取元素的attribute,根据前缀判断是否为指令,如果是指令就把指令名称截取出来,并交给对应的指令函数执行,然后将函数执行结果赋值给元素。

compileText()方法读取节点的nodeContent内容,使用replace将{{}}中的数据进行替换,然后把替换后的内容赋值给nodeContent。

class Compiler{constructor(el, vm){// 判断el属性是不是一个元素,如果不是元素就获取元素this.el = this.isElementNode() ? el : document.querySelector(el);this.vm = vm;let fragment = this.nodeToFragment(this.el);// 把内容进行替换// 编译模板用数据编译this.compile(fragment);// 把内容塞到页面中去this.el.appendChild(fragment)}//是不是元素节点isElementNode(node){return node.nodeType === 1; }// 把节点移动到内存中nodeToFragment(node){let fragment = document.createDocumentFragment();let firstChild ;while(firstChild = node.firstChild){fragment.appendChild(firstChild);}return fragment;}
// 编译内存中的dom节点compile(){let chileNodes = node.chileNodes;[...chileNodes].forEach(child => {if(this.isElementNode(child)){this.compileElement(child);this.compile(child);} else {this.compileText();}})}// 解析文本节点compileText(node){// 判断节点的内容中是否存在{{}}let content = node.textContent;if(/\{\{(.+?)\}\}/.test(content)){CompileUtil['text'](node, content, this);}}// 判断是否是指令isDirective(attrName){return attrName.startWith('v-');}// 解析元素节点compileElement(node){let attributes = node.attributes;[...attributes].forEach(attribute => {let {name,value:expr} = attribute;if(this.isDirective(name)){let [, directive] = name.split('-');CompileUtil[directive](node, expr, this.vm);}})}
}

CompilUtil对象是一个工具对象,为Compiler提供辅助函数,主要对解析元素中的指令和插值表达式操作进行分解并对部分操作进行复用。

CompileUtil = {// 获取指定元素的valuegetValue(vm, expr){expr.split('.').reduce((data, current) => {return data[current];}, vm.$data);},// v-model指令解析工具函数model(node, expr, vm){let fn = this.updater['modelUpdater'];let value = this.getValue(vm, expr);fn(node, value);},// 文本节点解析工具函数text(node,expr, vm){let content = expr.replace(/\{\{(.+?)\}\}/g, (...args) => {return this.getValue(vm, args[1]);});},// 更新元素的值updater:{modelUpdater(node,value){node.value = value;}}
}

将编译器应用于Vue中

class Vue{constructor(options){this.$el = options.el;this.$data = options.data;// 根元素存在编译模板if(this.$el){new Compiler(this.$el, this);}}
}

相关内容

热门资讯

谈美优秀作文 谈美优秀作文3篇  在平凡的学习、工作、生活中,大家都不可避免地要接触到作文吧,作文是由文字组成,经...
春天作文500字 关于春天作文500字(精选24篇)  在学习、工作乃至生活中,大家最不陌生的就是作文了吧,通过作文可...
第一次独自坐公交车作文500... 第一次独自坐公交车作文500字(精选21篇)  在日常学习、工作或生活中,大家都经常接触到作文吧,作...
秋天的记忆作文 秋天的记忆作文3篇  在学习、工作、生活中,大家总免不了要接触或使用作文吧,作文是人们把记忆中所存储...
爱的温暖600字作文 爱的温暖600字作文我需要什么呢?床也不能使我轻松,我好像在寻找一种什么依靠。我想到了爱,因为它是温...
失落的爱作文650字 关于失落的爱作文650字  每个人都有追求幸福的权利,追求并没有错。可幸福究竟是什么?有的人终其一生...
回忆作文500字 回忆作文500字(精选27篇)  在平平淡淡的学习、工作、生活中,许多人都有过写作文的经历,对作文都...
新学期收获的作文 关于新学期收获的作文  在日常学习、工作抑或是生活中,大家都接触过作文吧,作文是人们以书面形式表情达...
《这样的人让我叹息》作文55... 导语:寂静的一个夜晚,我听到一声叹息……是谁,是谁在叹息?淑地,发觉,是我……第一次叹息,在很小很小...
小猴子(3)作文 小猴子(3)作文小猴子(3)  小猴子的哥哥终于回国了,小猴子也过起了平静的生活,直到有一天……  ...
一句名言警句 一句名言警句  无论是身处学校还是步入社会,大家都有令自己印象深刻的名言警句吧,名言警句主要是指人们...
朋友,场友and荷友 朋友,场友and荷友  她,是我曾经的一个朋友;她,是我的一个场友;她,也是我的荷友!       ...
孝顺作文300字 关于孝顺作文300字(精选36篇)  在学习、工作乃至生活中,说到作文,大家肯定都不陌生吧,作文要求...
神鸟的故事作文 神鸟的故事作文从前,在北边的山林里,有一只聪明伶俐、会说话的神鸟。有一个国王,他有一个女儿,叫娜格尔...
镌刻的约定作文 镌刻的约定作文(精选68篇)  无论是在学校还是在社会中,许多人都有过写作文的经历,对作文都不陌生吧...
田径运动会作文 田径运动会作文15篇  在日常学习、工作和生活中,大家总少不了接触作文吧,作文是人们以书面形式表情达...
我想长大的作文500字 我想长大的作文500字(精选47篇)  在日常的学习、工作、生活中,大家都写过作文,肯定对各类作文都...
四年级想象作文:假如我会变 四年级想象作文:假如我会变  在学习、工作或生活中,大家都有写作文的经历,对作文很是熟悉吧,通过作文...
青春之歌作文 青春之歌作文(精选71篇)  在日常学习、工作或生活中,许多人都写过作文吧,写作文是培养人们的观察力...
寻找美丽的秋天作文 寻找美丽的秋天作文寻找美丽的秋天作文1  在我们平凡的日常里,大家总少不了接触作文吧,作文一定要做到...