1.Vue原理(大厂必考)
首先 原理 != 源码
1.1 组件化
数据驱动视图(MVVM,setState):传统组件,知识静态渲染,更新还要依赖于操作DOM
数据驱动视图-Vue MVVM 通过修改数据,驱动视图
数据驱动视图-React setState
1.2 响应式
- 组件data的数据一旦变化,立刻触发视图的更新
- 实现数据驱动视图的第一步
- 考察Vue原理的第一题
监听data变化的核心API:Object.defineProperty
Object.defineProperty的一些缺点(Vue3.0启用Proxy):
1)Proxy有兼容性的问题。兼容性不好,且无法polyfill
2) Vue2.x还会存在一段时间
3)Vue3.0
Object.defineProperty 基本用法
Object.defineProperty 实现响应式
- 监听对象,监听数组
- 复杂对象,深度监听
Object.defineProperty 缺点
- 深度监听,需要递归到底,一次性计算量大
- 无法监听新增属性/删除属性(Vue.set Vue.delete)
- 无法原生监听数组,需要特殊处理
1.3 vdom和diff
vueReact%0A_diffvdom%0A_vdom%0A_DOM%0A_jQueryDOM%0A_VueReact%0A_vdom%0A_vdom_jsDOMDOM%0A_httpsimgblogcsdnimgcn2020051321291880pngxossprocessimagewatermarktype_ZmFuZ3poZW5naGVpdGkshadow_10text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0NTRE5fYmFyZQsize_16color_FFFFFFt_70%0A_snabbdom_vdom%0A_vdom%0A_Vuevdomdiff%0A_React_vdom_vue_32">vdom是实现vue和React的重要基石
diff算法是vdom中最核心、最关键的部分
vdom是一个热门话题,也是面试中的热门问题
DOM操作非常耗费性能
以前用jQuery,可以自行控制DOM操作的时机,手动调整
Vue和React是数据驱动视图
解决方案-vdom
vdom 用js模拟DOM结构,计算出最小的变更,操作DOM
通过snabbdom 学习vdom
简洁强大的vdom库,易学易用
Vue参考它实现的vdom和diff
React vdom 具体实现和vue也不同,但不妨碍同一学习
diff算法是vdom中最核心、最关键的部分
diff算法能在日常使用Vue React中体现出来(如key)
diff算法是前端热门话题,面试“宠儿”
diff算法概述
diff即对比,是一个广泛的概念,如linux diff 命令、Git diff 等
两个js 对象也可以做diff
两棵树做diff,如这里的vdom diff
树diff的时间复杂度0(n^3)
第一,遍历tree1,第二遍历tree2
第三,排序
1000个节点,要计算1亿次,算法不可用
优化时间复杂度到o(n)
只比较同一层级,不跨级比较
她给不相同,则直接删掉重建,不在深度的比较
tag和key,两者都相同,则认为是相同节点,不在深度比较
深入diff算法源码生成vnode
- snabbdom
- patch
- patchVnode
- addVnodes removeVodes
- updateChildren(key的重要性)
不使用key VS 使用key
vdom核心概念很重要:h、vnode、patch、diff、key
vdom存在的价值更加重要:数据驱动视图,控制DOM操作
1.5 渲染过程
前置知识:js的with语法
vue template complier将模板编译为render函数
执行render函数生成vnode
with语法(非必须不建议用)
改变{}内自由变量的查找规则,当做obj属性来查找
如果找不到匹配的obj属性,就会报错
with要慎用,它打破了作用域规则,易读性变差
编译模板
模板不是html,有指令,插值,js表达式,能实现判断,循环
html是标签语言,只有js才能实现判断,循环
因此,模板一定是转换为某种js代码,即为编译模板
模板编译为render函数,执行render函数返回vnode
基于vnode再执行patch和diff
使用webpack vue-loader,会在开发环境下编译模板(重要)
vue组件中使用render代替template
在有些复杂的情况下不能用template,可以考虑用render
三大核心知识点:
响应式:监听data属性getter setter(包括数组)
模板编译:模板到render函数,再到vnode
vdom:patch(elem,vnode)和patch(vnode,newVnode)
组件渲染/更新的过程
初次渲染过程:
1)解析模板为render函数(或在开发环境已完成,vue-loader)
2)触发响应式,监听data属性getter setter
3)执行render函数,生成vnode,patch(elem,vnode)
更新过程:
1)修改data,触发setter(此前在getter中已被监听)
2)重新执行render函数,生成newVnode
3)patch(vnode,newVnode)
完成流程图
异步渲染:
回顾$nextTick
汇总data的修改,一次性更新视图
减少DOM操作次数,提高性能
总结1:
渲染和响应式的关系
渲染和模板编译的关系
渲染和vdom的关系
总结2:
初次渲染过程
更新过程
异步渲染
1.6前端路由
稍微复杂一点的SPA,都需要路由
vue-router也是vue全家桶的标配之一
属于“和日常使用相关联的原理”,面试常考
hash
hash变化会触发网页跳转,即浏览器的前进、后退
hash变化不会刷新页面,SPA必需的特点
hash永远不会提交到server端(前端自生自灭)
H5 history
用url规范的路由,但跳转时不刷新页面
history.pushState
window.onpopstate
正常页面浏览
改造成H5 history模式
总结
hash-window.onhashchange
H5 history-history.pushState和window.onpopstate
H5 history需要后端的支持
两者如何选择
to B的系统推荐用hash , 简单易用,对url规范不敏感
to C的系统,可以考虑选择H5 history , 但需要服务端支持
能选择简单的,就别用复杂的,要考虑成本和收益(工作很现实)
Vue原理总结
组件化 :
组件化的历史、数据驱动视图、MVVM
模板编译 :
◆with 语法
◆模板编译为render函数
◆执行render函数生成vnode
响应式 :
◆Object.defineProperty
◆监听对象(深度) , 监听数组
◆Object.defineProperty的缺点( Vue 3用Proxy, ,后面会讲)
渲染过程:
◆初次渲染过程
◆更新过程
◆异步渲染
vdom和diff :
应用背景、vnode结构、snabbdom使用: vnode h patch
前端路由:
◆hash
◆H5 history
◆两者对比