1、如何理解 MVVM
很久以前就有组件化(ASP JSP PHP 已经有组件化了、nodejs 中也有类似的组件化):传统组件,只是静态渲染,更新还依赖操作dom;
数据驱动视图(MVVM,setState):vue MVVM (model-view-viewmodel)、react setState
2、vue 响应式
组件 data 的数据一旦变化,立刻触发视图更新
实现数据驱动视图的第一步
核心API:Object.defineProperty
(vue 3.0 使用 proxy,proxy有兼容性问题,且无法polyfill )
Object.defineProperty 实现响应式: 监听对象,监听数组
Object.defineProperty 的缺点:
深度监听,需要递归到底,一次性计算量大
无法监听新增属性/删除属性(Vue.set Vue.delete)
无法原生监听数组,需要特殊处理
3、vue 如何监听数组变化
4、虚拟dom (vdom)
dom操作非常耗费性能
以前用jquery,可以自行控制dom操作时机,手动调整
vue 和 react 是数据驱动视图,如何有效控制dom操作?
解决方案-vdom:
用js模拟dom结构(vnode)
新旧vnode对比,得出最小的更新范围,最后更新dom
数据驱动视图模式,有效控制dom操作
5、diff算法
diff即对比,是一个比较广泛的概念,如Linux diff命令、git diff等
两个js对象也可以做diff
树diff 的时间复杂度o(n^3)
第一,遍历tree1;第二,遍历tree2;第三,排序;如果节点树过大,算法不可用
优化时间复杂度到 o(n):
只比较同一层级,不跨级比较
tag不相同,则直接删掉重建,不再深度比较
tag 和 key ,两者相同,则认为是相同节点,不再深度比较
patchVnode、addVnode、removeVnode、updateChildren
6、模板编译
模板是vue开发中最常用的部分,即与使用相关联的原理
模板不是html,有指令、插值、js表达式,能判断、循环,因此,模板一定是转换为某种js代码,即编译模板
vue template compiler 将模板编译为 render 函数
模板编译为render函数,执行render函数 返回vnode
基于vnode 再执行 patch 和 diff
使用webpack vue-loader, 会在开发环境下编译模板
7、with语法
8、组件 渲染/更新过程
响应式:监听data属性 getter setter
模板编译: 模板到render函数,再到vnode
vdom: patch(elem, vnode) 和 patch(vnode, newVnode)
初次渲染过程:
解析模板为render 函数(或在开发环境已完成,vue-loader)
触发响应式,监听data属性 getter setter
执行render函数,生成 vnode, patch(elem, vnode)
更新过程:
修改data,触发setter(此前在getter中已被监听)
重新执行render 函数,生成newVnode
patch(vnode,newVnode)
9、前端路由原理
hash 的特点:
hash 变化会触发网页跳转,即浏览器前进和后退
hash变化不会刷新页面
hash永远不会提交到server端
window.onhashchange
h5 history:
用URL规范的路由,但跳转时不刷新页面
history.pushState
window.onpopstate