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

Vue原理(一)

时间:2023-04-01 12:59:10 vue.js

组件化和MVVM组件化传统组件只是静态渲染,更新也依赖于操作DOM。数据驱动视图-VueMVVM。更多地关注数据和业务逻辑。MVVMMVCModeldata→View视图→Controller控制器MVVMMMVVM——ModelViewViewModel,data,view,视图模型model对应data,view对应template,vm对应newVue({...})三者的关系:view可以通过事件绑定模型可以影响模型,模型可以通过数据绑定影响视图,而viewModel是连接模型和视图的连接器。MVVM框架的三大要素是响应式的:Vue如何监听数据模板引擎的每个属性变化:Vue模板是如何解析的,指令是如何渲染的:Vue模板是如何渲染成html的,渲染过程是响应式的:组件数据的数据一旦发生变化,会立即触发视图的更新。数据属性被代理到虚拟机。实现数据驱动视图的第一步。Object.definedProperty是监控数据变化的核心API。Object.definedProperty的基本用法可以直接在一个对象上定义一个新的属性,或者修改一个对象已有的属性,并返回这个对象。Vue.js正式采用这种方式实现数据的双向绑定,达到响应式的目的。通过Object.definedProperty监听对象属性的get和set语法Object.defineProperty(obj,prop,descriptor)object:在其上添加或修改属性的对象。propertyname:包含属性名称的字符串。需要定义的是属性和方法。描述符:它可以包含以下属性。writable、enumerable、configurable默认为false,有两种方法(双向数据绑定使用这两种方法,即访问器)get()和set()访问set和getset();重新分配属性后,将自动调用此方法。得到();一旦属性被访问和读取,这个方法就会被自动调用。letdata={};letname='zhangsan';Object.defineProperty(data,"name",{get:function(){console.log("get");},set:function(newVal){console.log("set");name=newVal;}});console.log(data.name);//get//undefineddata.name="list";//setvue.js使用数据劫持结合publisher-subscribe在订阅者模式的方式中,通过Object.defineProperty()来劫持各个属性的setter和getter,当数据发生变化时,向订阅者发布消息并触发相应的监听回调。Object.definedProperty的几个缺点深度监控需要递归到底,一次计算量大。无法侦听新属性/删除属性。无法原生监控数组,需要特殊处理。vdom和diffvdom是vue的重要基石。diff算法是vdom最核心也是最关键的部分。Vdom(VirtualDOM)背景:使用我们传统的开发模型,当原生JS或JQ操作DOM时,浏览器会从构建DOM树开始,从头到尾执行这个过程。操作DOM的成本是昂贵的,频繁的操作还是会造成页面卡顿,影响用户体验。因此,提出:用js模拟DOM结构,计算最小变化,详细操作DOM:如果一次操作有10个更新DOM的动作,虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到一个本地的JS对象中,最后一次性attch这个JS对象到DOM树中,再进行后续的操作,避免了很多不必要的计算。意义:vdom的真正意义是实现跨平台、服务端渲染,提供性能良好的Dom更新策略。VirtualDOM渲染成真实DOM其实需要经过VNodedefinition、diff、patch等过程。VNodeVirtualDOM由VNodeClass描述。VNode的核心属性是tag属性,也就是这个vnode的tag属性。data属性包含最终渲染成真正的dom节点后,节点上的class、attribute、style和boundeventchildren属性就是vnode的子节点。文本属性是文本属性。elm属性是这个vnode对应的真实dom节点key属性。该属性是vnode的标记。diff过程中可以提高diff算法实现的效率1.用JS对象模拟DOM树**

vdom

  • a
  • {tag:"div",props:{}children:[{tag:'p',children:'vdom'},{tag:'ul',props:{style:'font-size:20px'},children:[{tag:"li",children:'a'}]}]}2.比较两个虚拟DOM树的区别—diffalgorithm**diff算法用于比较两个VirtualDOM树之间的差异。如果需要对两棵树进行完整的比较,diff算法的时间复杂度为O(n^3)。但是在前端,你很少跨层移动DOM元素,所以VirtualDOM只会比较同层的元素,div只会和同层的div比较,第二层的只会和第二层比较相比之下,算法的复杂度可以达到O(n)。flatlayerDiff的四种情况:节点替换:节点发生变化,例如将上面的div替换为h1;顺序交换:移动、删除、添加子节点,比如上面div的子节点,交换p和ul的顺序变化;attributechange:修改节点的属性,比如删除上面li的类样式类;textchange:改变text节点的文本内容,比如将上面p节点的文本内容改为“RealDom”;differenceobjects(patches):我们可以通过differenceobject得到两个虚拟DOM对象之间发生了哪些变化,从而根据differenceobject(patches)改变原来的真实DOM结构,从而改变DOM结构页。diff过程**主要是调用patchVnode方法进行的:diff过程有几种情况,oldCh是oldVnode的子节点,ch是Vnode的子节点:首先判断文本节点,如果oldVnode.text!==vnode.text,则直接替换文本节点;如果vnode没有文本节点,输入子节点的diff;当oldCh和ch都存在且不同时,调用updateChildren对子节点进行diff;如果oldCh不存在但ch存在,则先清空oldVnode的文本节点,同时调用addVnodes方法将ch添加到elm的真实dom节点中;如果oldCh存在但ch不存在,删除elm真实节点下的oldCh子节点;oldVnode有文本节点,而vnode没有,则清空这个文本节点。子节点diff过程分析为什么使用v-for时一定要加一个uniquekey?我们希望在B和C之间加一个F,Diff算法默认是这样执行的:即更新C为F,更新D为C,更新E为D,最后插入E,不是吗效率很低吗?所以我们需要用key为每个节点做一个唯一的标识,Diff算法才能正确识别这个节点,找到正确的位置插入新的节点。因此,key的作用主要是高效更新虚拟DOM。3.将两个虚拟DOM对象的差异应用到真实的DOM树上**