VUE,前端的一个js框架,相信只要是程序员都多少会听过一些,这篇文章几率一下我自学vue的一个过程。
首先如果没有五年编程基础的不建议阅读,因为你可能读不懂,尽管我想尽量将的基础一些,但是vue这个东西吧,涉及的东西还是比较广的。
我先概括一下vue,先打个预防针,如果知道js的构造函数,封装,我建议各位先把这些彻底搞清楚,如果不是能达到举一反三的效果,建议从头到尾好好学习一下js,看一遍,因为大部分人都是会用,但是并不知道为什么要这么用。一开始我也是这样,认为会用就行了,但是如果知道原理的话,起码对于新出的语言理解上还是会快的多。其次不至于有些东西看过当时会,不久就忘掉。如果出现这种情况,说明你只是记住了代码,并没有理解融汇贯穿,也就是没有变成自己的东西。OK,正题:
首先我先说一下关于VUE的几个原理重要点。
1、生命周期
2、响应式
3、双向绑定
4、虚拟dom
5、diff算法
其次还有使用的几个重要点。
1、安装
2、运行
3、发布
---------------------------------------------分割-----------------
生命周期:关于vue的生命周期,这是对于一直写原生js的程序员们最陌生的词。因为js自己根本没有什么生命周期之类的说法,但是有两个方法,相信老程序员们应该都听过:init方法,load方法。对,仔细想想当时为什么会写这种名字的方法,其实我们都已经对生命周期有一个概念了,只是很模糊。vue提出生命周期,只是把我们的模糊概念具体化了。vue在原生js的基础上,做了大部分人自己在做,但是没有为别人而做的事情。vue生命周期有BC、C、BM、M、BU、U、BD、D。BC其实就是一个init,vue的bc初始化了vue这个函数,里面包含了默认的一些事件、方法、属性(比如vue的那些语法糖)等等、但是这些事件属性方法不是用户定义的,是vue自己的。同时向外暴露一个可以给用户操作的对象参数vm。let vm = new VUE({...})。
vue在BC之后就会继续调用C,当我们在{…}中写上我们的代码时,vue在C中的逻辑就会为我们的{…}中代码做一遍处理,vue会循环我们的代码,并将我们声明的对象再次构造,比如给每一个对象、对象属性添加监听,以达到vue自己所谓的数据观测,事件监听效果,当vue的C完成后没有报错,说明我们的代码已经被vue构建成功了,已经包含了vue的一些特性。比如原生js的object.definproperty还有其下的get/set方法也已经被vue给重写了。这时通过vue的v-model指令,就可以完成双向数据绑定的效果了。当然,这时理论上可以,但是需要将vue的整体生命周期执行完毕后用户才可以看到效果。
当C完成后。继续vue的BM,BM做了很多事情,类似于HTTP的渲染过程,会解析我们的html,拆分成vue定义的叫做Vnode的对象节点,类似于XML,构建dom树,构建渲染树,渲染树也就是把css、js与html融合在一起的意思,再对渲染树进行一个布局,最后绘制成可供用户看的HTML。不过BM完成时,vue创建的只是虚拟dom,并没有真正渲染到页面,是存放在内存中的。在接下来M完成时候才会在页面呈现出来,也就是vue名词提到的挂载完成。
挂载完成之后用户就可以看到vue首次渲染出来的页面了。如果接下来用户操作,或者我们代码有异步函数等等操作,就会触发vue的BU/U周期,这里会用到vue的DIFF算法,目的就是效率问题,如果每次当触发操作需要更改dom都让代码整体渲染一遍就不是vue的语言目的了,diff算法下面我会拎出来单说。当然U完成之后还是会在此调用BM和M周期,挂载处理后的dom。
最后是BD/D,销毁。不多说。因为我个人感觉没啥用
双向绑定和响应式:其实他两个是一个东西,响应式只不过是双向绑定的模式。
响应式是说当操作后能够及时响应到页面,其根本就是vue的双向绑定造成的,vue通过刚才提到过的bc、c两个生命周期为我们的数据对象构造了watcher,同时又为每个属性重写了get、set,当对象属性发生操作时,会通知watcher,渲染与该对象属性相关联的所有dom。
虚拟dom上文中提到过一些,具体会在diff算法中一起细说。
OK,下面说一下diff算法与虚拟dom:
vue的diff算法原理核心就在于它的patch方法和same方法还有一个updatechild,vue在diff之前会将html解析成vnode对象,在做diff算法的过程中,才会构建新的dom,所以vnode和dom虽然有对应关系,但格式不同,这里一定要弄清楚,不然会乱。言归正传,首先虚拟dom也就是新vnode和老vnode也就是上一次被渲染的dom进行一个对比,把他两个都当做对象来看,如果相同,就会return,不做任何事情,如果不同,就会根据两个对象vnode的首个节点开始,逐级同级比较,注意!逐级同级的意思是以新vnode也就是虚拟dom为准,以上一次渲染成功的vnode为参数,新旧两个vnode,从初始阶段开始,同层级比较,第一,如果新的vnode节点存在于旧vnode中,且相同,则更新新的dom,如不同,就是说新的节点有子节点,旧的vnode没有子节点,则在新的dom上插入新的同层级子节点。第二,如果新的vnode节点不存在于旧vnode中,则整体插入。第三,如果旧的vnode节点不存在于新的vnode中,则移出旧的dom。到这里我们回到最开始,patch方法接受两个参数:新的vnode和旧的vnode,做对比,same方法也会接受两个参数,新vnode和旧vnode,用来判断两个vnode节点是不是相同。最后updatechild用来更新新的dom渲染。