赞
踩
Vue的绑定原理可以概括为:保护Data属性+观察这模式+新Dom树(虚拟)
Vue的绑定原理可以参看Vue的绑定原理
我们以下面的代码为例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <h5>Vue</h5> <p>计数:<span>{{count}}</span></p> <h5>hello word</h5> <p>计次:<span>{{num}}</span></p> <p>计数:<span>{{count}}</span></p> </div> <script> var data = { count: 1, num: 0, }; new Vue({ el: "#app", data: data, }); </script> </body> </html>
效果图
代码执行流程
上面是代码的执行流程,和Vue的绑定原理图。我们就可以根据上面的图使用Object.definedProperties()模拟Vue的绑定原理。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div id="app"> <h5>Vue</h5> <p>计数:<span>{{count}}</span></p> <h5>hello word</h5> <p>计次:<span>{{num}}</span></p> <p>计数:<span>{{count}}</span></p> </div> <script> var data = { num: "zhengwenda", count: 1, }; //一、改造data对象的属性,并保护data中的每个属性 // 1. 使用Object.keys来遍历data的属性名; var keys = Object.keys(data); console.log(keys); //Vue的绑定原理,保护data属性,并创建get,set方法 //这里因为不确定data里面有多少个属性,所以这里使用for of 循环遍历data的属性 for (var key of keys) { //这里使用匿名函数自调,如果不使用匿名函数自调,获得的key就不是当前需要的key,而是遍历当最后一个属性 //所以这里需要使用匿名函数自调 //key是局部变量 //每遍历data中的一个变量,就要改造这个变量 (function (key) { console.log(key); Object.defineProperties(data, { //保护当前的变量,定义一个"_key"变量来保护原变量 //在定义对象时,属性名禁止使用模板字符串 所以不能用`_${key}`定义属性名 //在定义对象时,属性名禁止使用拼接字符串 所以不能用“_”+{key}定义属性名 //ES6语法新语法,专门用于动态生成属性名,这里只能使用[拼接字符串或模板字符串]的方式定义属性名 [`_` + key]: { value: data[key], writable: true, enumerable: false, //半隐藏 }, //用一个和当前属性同名的访问器属性,替代data中的原普通属性 [key]: { get() { return this[`_${key}`]; }, set(value) { this[`_${key}`] = value; console.log(`${key}发生了变化`); change(key); }, enumerable: true, }, }); })(key); } //密封 每个属性的configurable:false; Object.seal(data); console.log(data); setInterval(function () { data.count += 1; }, 1000); //二、创建虚拟Dom树 //先定义个数组,存放虚拟Dom树 var arr = []; //定义一个函数,来扫描真实Do树 function getChildren(parent) { var children = parent.children; //使用递归遍历出所有Dom树, for (var c of children) { if (c.children.length > 0) { //递归调用,如果还有子节点 arguments.callee(c); } else { for (var key of keys) { //判断内容是不是{{}}的如果是 if (c.innerHTML == `{{${key}}}`) { //将c和c.innerHTML存入数组中, arr.push({ elemt: c, innerHTML: c.innerHTML, }); //页面初次渲染时,将对应的属性值赋值给{{}} c.innerHTML = data[key]; } } } } } //传入根节点 getChildren(document.getElementById("app")); console.log(arr); //如果set发生变化时,会通知给观察者进行修改,这个change相当于观察者 function change(key) { //遍历虚拟Dom树,将新值赋值给对应的{{}} for (var obj of arr) { if (obj.innerHTML == `{{${key}}}`) { obj.elemt.innerHTML = data[key]; } } } </script> </body> </html>
效果图
控制台输出
这样就基本实现出Vue的绑定原理,使用Object.defineProperties()模拟实现出Vue的绑定原理
东哥笔记
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。