一、js/TemplateCompiler.jscss
//建立模板编译工具TemplateCompiler class TemplateCompiler{ //构造函数 //视图线索,全局vm对象 constructor(el,vm){ //缓存重要属性 this.el=this.isElementNode(el)?el:document.querySelector(el); this.vm=vm; //判断视图存在 if(this.el){ //编译工具要作的核心的三件事 var fragment = this.node2fragment(this.el); //一、把模板内容放入内存 //debugger; //断点测试 this.compile(fragment); //二、解析模板 this.el.appendChild(fragment); //三、把内存结果返回到页面中 } } //*************工具方法(自定义)********************* isElementNode(node){ return node.nodeType === 1; //1元素节点,2属性节点,3文本节点 } isTextNode(node){ return node.nodeType === 3; } toArray(fakeArr){ //将假数组转为真数组,以假乱真 return [].slice.call(fakeArr) } isDirective(attrName){ //判断传入内容是否为指令,好比判断v-text return attrName.indexOf('v-') >=0; //判断属性名中是否有'v-'开头的 } //*************核心方法********************* //把模板放入内存,等待解析 node2fragment(node){ var fragment = document.createDocumentFragment(),child; //(1)、建立内存片断 //debugger; //断点测试 while(child = node.firstChild){ //(2)、把模板内容丢到内存,循环读取 fragment.appendChild(child); } return fragment; //(3)、返回 } compile(parent){ var childNodes=parent.childNodes, //(1)、获取字节点 complier = this; //缓存当前的对象 //(2)、一个个解析。遍历每个节点 this.toArray(childNodes).forEach((node)=>{ //正常写法转为箭头写法:function(node)变为(node)=> //(3)、判断节点类型,元素节点、文本节点 if(complier.isElementNode(node)){ //若是是元素节点,就进行解析 complier.compileElement(node); //解析标签的方法 } //(4)、若是还有节点,继续解析 }); } //专门解析元素节点指令的 compileElement(node){ var arrs = node.attributes, //(1)获取当前节点的全部属性,即得到一堆数组 complier = this; //(2)、遍历当前元素的全部属性 this.toArray(arrs).forEach(attr=>{ var attrname= attr.name; if(complier.isDirective(attrname)){ //(3)判断属性是不是指令 //(4)、收集信息,指令类型, //var type = attrname.split('-')[1]; //T一、先找到v-text的'-',而后下标为1开始截取 var type = attrname.substr(2); //T二、或者从下标为2开始截取 var expr = attr.value; //表达式 //(5)、找帮手 debugger; CompilerUtils[type](node,complier.vm,expr); } }); } //解析表达式 compileText(){} } //榜手,普通对象,提供以一系列工具、方法为咱们作事 CompilerUtils={ //解析text指令的方法 text(node,vm,expr){ //(1)、找到更新规则对象的更新方法 var updaterFn = this.updater['textUpdater']; //(2)、执行方法 updaterFn && updaterFn(node,vm.$data[expr]); //先判断是否存在 //updaterFn() }, model(node,vm,expr){ //(1)、找到更新规则对象的更新方法 var updaterFn = this.updater['modelUpdater']; //(2)、执行方法 updaterFn && updaterFn(node,vm.$data[expr]); //先判断是否存在 //updaterFn() }, updater:{ textUpdater(node,value){ //文本的更新方法 node.textContent = value; }, modelUpdater(node,value){ //文本框的更新方法 node.value = value; } } //更新规则对象 }
二、js/mvvm.js文件html
//建立一个MVVM框架的类,主要是打包mvvm框架作的事情。 //var a=100; //function fn(){ } //做用是用来解析视图模板,把对应的数据渲染到页面上 class MVVM{ //类是用来建立实例的 //构造器,建立实例的模板代码 constructor(options){ //缓存重要属性,视图、数据 this.$vm=this; //先绑定本身 this.$el=options.el; this.$data=options.data; //判断视图是否存在 if(this.$el){ //建立模板编译器来解析视图 this.$TemplateCompiler = new TemplateCompiler(this.$el,this.$data); } } }
三、MyHtml.html文件vue
<!DOCTYPE html> <html> <head> <title>MyHtml.html</title> <meta name="keywords" content="keyword1,keyword2,keyword3"> <meta name="description" content="this is my page"> <meta name="content-type" content="text/html; charset=UTF-8"> <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> </head> <body> <!--一、建立一个视图容器,两种方式。<br>是换行、input输入框--> <div id='app'> <span v-text='message' class='XXXX'> </span> <br> <!-- {{message}} <br> --> <!-- 经过视图输入框去改变数据 --> <input type='text' v-model='message'> <div v-text='username'> </div> </div> <!--二、引入cdn框架,后改成本身的框mvvm架,而后将new Vue改成new MVVM--> <!-- <script src="https://cdn.bootcss.com/vue/2.5.16/vue.js"></script> --> <script src="./js/templateCompiler.js"></script> <script src="./js/mvvm.js"></script> <!--三、编辑脚本,做为桥梁把数据扔到html页面上--> <script> //创建全局变量vm,在网页上右键审查元素,输入vm可获取vm参数,而后输入vm.message回车便可访问message var vm = new MVVM({ //挂载视图,把显示的绑过来 el: '#app', //定义数据,把数据源绑过来 data:{ message:'欢迎进入机器学习和深度学习的世界!', username:'元宝' } }) </script> </body> </html>
一、正在寻找答案……node