模板解析
模板解析流程:
- 将el的所有节点取出,放在文档碎片fragment对象中
- 将fragment对象的所有子节点进行递归解析处理
插值语法解析
-
- 对插值语法(表达式)进行解析(与v-text指令解析一致),使用compileText方法
- 根据正则对象获取匹配到的表达式字符串
- 从vm实例上找到表达式对应的值
- 将属性值设置为文本节点的textContent
- 对插值语法(表达式)进行解析(与v-text指令解析一致),使用compileText方法
指令解析
-
- 一般指令解析
- 从标签节点中获取到指令名和表达式
- 从vm实例上拿到表达式的对应的值
- 根据指令操作标签节点的属性
- 一般指令解析
v-text----textContent属性
v-html----innerHtml属性
v-class----className属性
v-model----value属性
-
-
- 将表达式的值设置到对应的属性上
- 指令解析后,移除元素此属性
- 事件指令解析
- 从标签节点找到获取到对应的事件名和表达式
- 根据表达式从vm实例methods中获取到函数
- 给当前元素节点绑定指定的事件名和回调函数
- 指令解析后,移除元素此属性
-
- 将解析后的文档对象fragment添加到el中显示
相关代码
mvvm.js
//编译模板 this.$compile = new Compile(options.el || document.body, this); |
compile.js
function Compile(el, vm) { // 保存vm this.$vm = vm; //为了能在其他函数内部获取到vm实例身上的数据 // 获取dom元素保存起来 this.$el = this.isElementNode(el) ? el : document.querySelector(el);
if (this.$el) { // 1. 将元素所有子节点添加到新的创建文档碎片节点中 this.$fragment = this.node2Fragment(this.$el); // 2. 递归编译文档碎片节点所有子节点 this.init(); // 3. 将编译好文档碎片节点添加到页面中生效 this.$el.appendChild(this.$fragment); } } node2Fragment—得到文档随便对象 node2Fragment: function (el) { // 创建文档碎片节点 var fragment = document.createDocumentFragment(), child; // 将原生节点拷贝到fragment while ((child = el.firstChild)) { fragment.appendChild(child); } return fragment; }, Init—开始编译 init: function () { // 递归编译所有子节点方法 this.compileElement(this.$fragment); }, compileElement—接收文档碎片进行编译 compileElement: function (el) { // 取出当前元素所有子节点 var childNodes = el.childNodes, me = this; // 转换成数组进行遍历< |