当前位置: 首页 > Web前端 > vue.js

数据驱动2_Vue源码_适合初学者

时间:2023-03-31 19:24:32 vue.js

解决上一篇文章的不足:Vdom(类似深拷贝)只是简单的整合了属性级的数据值和路径(函数柯里化技术)为什么是Vnode?一个标签上的属性如此之多,不断的插入删除难免会造成浏览器卡顿,为了优化页面加载速度,提高性能,Vnode以JS对象的形式存储了dom节点。比如动态创建和添加只用到这几个属性:nodeValue,nodeName,nodeType,attributes..vdom:构造函数形式:classVnode{constructor(tag,data,value,nodeType){this.tag=tag&&tag.toLowerCase();//=>1this.data=数据;this.value=值;this.nodeType=nodeType;这个.child=[];//=>2}appendChild(vnode){this.child.push(vnode);}}functiongetVnode(node){lettype=node.nodeType;让_vnode=null;if(type===1){//=>3letnodeName=node.nodeName;让attri=node.attributes;让attr={};//=>4for(leti=0;i5让childNodes=node.childNodes;//=>6for(leti=0;i1.tag不能是undefined,所以tag必须存在并转为小写_vnode=newVnode(undefined,undefined,node.nodeValue,type);}返回_vnode;}letnode=document.querySelector("#app");letvnode=getVnode(node);console.log(vnode);//=>2.考虑label中的子元素,添加nodeone

代码截图:详情:1.tag通过getVnode传递。如果dom节点是文本节点,那么tag是undefined2.child是数组,因为tag元素有子元素,所以childNodes有子元素,所以调用实例的appendChild方法和递归3.检查type类型。如果是元素节点,则有tag和data,就是class、id等属性。去掉属性后,这是一个伪数组。4.js是作为对象存储的,所以伪数组必须转为对象。存储5.开始实例化对象,元素节点会传tag的参数,文本节点会传文本节点的参数6.如果是节点元素,检查是否有子节点,简单整合letNameObj={hobby:'ilove',name:{firstName:'i',lastName:'mycode'}}letvm=newivue({el:'#app',data:data})functionivue(选项){this._data=options.data;这个._el=选项.el;//模板和数据拿到this._tmp=document.querySelector(this._el);this._parent=this._tmp.parentNode;//=>bodythis.render();}ivue.prototype.render=function(){this.compiler();}ivue.prototype.compiler=function(){letrealHtmlDOM=this._tmp.cloneNode(true);编译器(realHtmlDOM,this._data);this.uopdate(realHtmlDOM);}ivue.prototype.update=function(real){this._parent.replaceChild(real,document.querySelector('#app'))}varregExp=/\{\{(.+?)\}\}/G;//=>确定正义验证字串规则functioncompiler(template,data){varchildNodes=template.childNodes;//=>1for(leti=0;i2if(type===3){//=>3lettxt=childNodes[i].nodeValue;txt=txt.replace(regExp,(_,g)=>{letkey=g.trim();//=>4letvalue=data[key];//=>5返回值;});//=>6个子节点[i].nodeValue=txt;//=>7}elseif(type===1){//=>8compiler(childNodes[i],data);}}}{{hobby}}
多属性路径取值问题让我们思考这个问题,当我们要使用对象下的某个属性时,我们传入=>object.path.path直到找到想要的对象名,在vue中如何实现多层路径访问?事实上,你需要使用函数柯里化技术functiongetValueByPath(O,path){//=>O是对应的`object`letpaths=path.split(".");让res=O;让支柱;while((prop=paths.shift())){res=res[prop];}返回资源;}letvalue=getValueByPath(objName,"name.lastName");让我们看一下我们用来查找对象的路径。现在对象作为参数传递给要处理的函数。O通过split('.')代替us进行拦截和压入。Intercept会得到一个类似于['name','firstName','lastName']的数组然后我们循环遍历,使res=O[name]=>objName[name]=>{firstName:'..',lastName:'..'}如果结果在循环中得到了firstName,多亏了prop,我们每次都会深入currying:curryingtechnique,vue中的数据一直在变化,path路径只要写完就死了。我们可以这样,先写路径,这样编译的时候直接执行,全局使用createValueByPa函数日(路径){让路径=path.split(".");返回函数getValueByPath(O){让res=O;让支柱;while((prop=paths.shift())){res=res[prop];}返回资源;};}让getValueByPath=createValueByPath("name.firstName");让value=getValueByPath(objName);文档.write(值);letobjName={name:{firstName:"MrsBob",lastName:"LiVison"}};