vue原理相关
vue原理三大模块:响应式、vdom和diff、模板编译
vue原理要点:
1、组件化
组件化的历史:在vue之前已经有组件化的概念了,想asp、jsp、php等就有组件化的概念,nodejs也有组件化
数据驱动视图:传统组件都只是静态渲染,国内新年还是要依赖于操作DOM,现在的网页复杂度高,操作DOM变得不太实际。于是便有脸VUE MVVM通过数据去驱动视图
MVVM:
2、响应式
Object.defineProperty
监听data属性getter setter (包括数组)
监听对象(深度),监听数组
重新定义数组原型,创建新对象,原型指向oldArrayProperty,再扩展新的方法,所以不会影响原型
Object.defineProperty的缺点
1)深度监听,需要递归到底,一次性计算量大;
2)无法监听新增属性/删除属性(需要用vue.set vue.delete)
3)无法监听原生数组,需要特殊处理
3、vdom和diff
应用背景:DOM操作给常耗时,以前用jQuery,可以自行控制DOM操作时机,手动调整,Vue 和 React 是数据驱动视图,可以有效控制DOM操作,Vdom-js执行速度快,用哪个JS模拟DOM结构,计算出最小变更,做操DOM。
DOM-Diff:diff是发生在虚拟 DOM 上的,将新虚拟 DOM 和旧虚拟 DOM进行 diff (精细化比较),得出最小的更新范围,最后反映到真实的 DOM 上的一个过程,这个过程其实是一个patch(补丁)过程,即指对旧的VNode进行修补,打补丁从而得到新的VNode。
vdom结构:
Diff算法总结:
PatchVnode
addVnodes removeVnodes
updateChildren(key的重要性)
4、模板编译
1)with语法;
2)(vue template complier)模板编译为render函数;
3)执行render函数生成vnode
5、渲染过程
1)初次渲染过程
- 解析模板为render函数(或在开发环境已完成,vue-loader)
- 触发响应式,监听data属性getter setter
- 执行render函数,生成vnode,patch(elem,vnode)(执行render函数会触发getter)
2)更新过程
- 修改data,触发setter(此前已经在getter中被监听)
- 重新执行render函数,生成nreVnode
- Patch(vnode,newVnode)
3)异步渲染
- 汇总data的修改,一次性更新视图
- 减少DOM操作次数,提高性能
- 简述:
当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。
这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。
每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。
- 深入理解:
监听器 Observer:对数据对象进行遍历,包括子属性对象的属性,利用 Object.defineProperty() 对属性都加上 setter 和 getter。这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化。
解析器 Compile:解析 Vue 模板指令,将模板中的变量都替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,调用更新函数进行数据更新。
订阅者 Watcher:Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁 ,主要的任务是订阅 Observer 中的属性值变化的消息,当收到属性值变化的消息时,触发解析器 Compile 中对应的更新函数。每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新——这是一个典型的观察者模式
订阅器 Dep:订阅器采用 发布-订阅 设计模式,用来收集订阅者 Watcher,对监听器 Observer 和 订阅者 Watcher 进行统一管理。
6、前端路由
1)hash
hash变化会触发网页跳转,即浏览器的前进、后退
hash变化不会刷新页面,SPA必需的特点
hash永远不会提交到server端(前端自生自灭)
触发hash变化的方式:
通过js修改
修改路由
浏览器的前进后退
2)H5 history
用url规范的路由,但跳转时不刷新页面
History.pushState--路由切换
window.onpopstate--监听浏览器前进后退
3)两者对比
hash--通过window.onhashchange监听
H5 history--通过window。onpopstate监听,history。pushState修改
H5 history需要后端支持
toB的系统推荐使用hash,简单易用,对url规范不敏感
toC系统,可以考虑选择H5 history,但需要服务端支持
能选用简单的就别用复杂的,要考虑成本和收益