1.组件化和MVVM
2.响应式原理
3.vdom和diff算法
4.模板编译
5.组件渲染过程
6.前端路由
传统组件,知识静态渲染,更新依赖于操作DOM
数据驱动视图 - Vue MVVM
MVVM是Model-View-ViewModel缩写,也就是把MVC中的Controller演变成ViewModel。Model代表数据模型,View代表UI组件,ViewModel是View和Model层的桥梁,数据会绑定到ViewModel层并自动将数据渲染到页面中,视图变化的时候通知viewModel层更新数据
组件data的数据一旦改变,立马触发视图的更新。
核心API -- Object.defineProperty
Object.defineProperty有缺点(Vue3启用Proxy)
Proxy的兼容性不太好,且无法使用polyfill
Object.defineProperty基本用法
Object.defineProperty实现响应式
Object.defineProperty的缺点
总结;
1.核心API -- Object.defineProperty
2.如何监听对象(深度监听),如何监听数组
3.缺点
// 触发更新视图
function updateView() {
console.log('视图更新')
}
// 重新定义数组原型
const oldArrayProperty = Array.prototype
// 创建新对象,原型指向 oldArrayProperty ,再扩展新的方法不会影响原型
const arrProto = Object.create(oldArrayProperty);
['push', 'pop', 'shift', 'unshift', 'splice'].forEach(methodName => {
arrProto[methodName] = function () {
updateView() // 触发视图更新
oldArrayProperty[methodName].call(this, ...arguments)
// Array.prototype.push.call(this, ...arguments)
}
})
// 重新定义属性,监听起来
function defineReactive(target, key, value) {
// 深度监听
observer(value)
// 核心 API
Object.defineProperty(target, key, {
get() {
return value
},
set(newValue) {
if (newValue !== value) {
// 深度监听
observer(newValue)
// 设置新值
// 注意,value 一直在闭包中,此处设置完之后,再 get 时也是会获取最新的值
value = newValue
// 触发更新视图
updateView()
}
}
})
}
// 监听对象属性
function observer(target) {
if (typeof target !== 'object' || target === null) {
// 不是对象或数组
return target
}
// 污染全局的 Array 原型
// Array.prototype.push = function () {
// updateView()
// ...
// }
if (Array.isArray(target)) {
target.__proto__ = arrProto
}
// 重新定义各个属性(for in 也可以遍历数组)
for (let key in target) {
defineReactive(target, key, target[key])
}
}
// 准备数据
const data = {
name: 'zhangsan',
age: 20,
info: {
address: '北京' // 需要深度监听
},
nums: [10, 20, 30]
}
// 监听数据
observer(data)
// 测试
// data.name = 'lisi'
// data.age = 21
// // console.log('age', data.age)
// data.x = '100' // 新增属性,监听不到 —— 所以有 Vue.set
// delete data.name // 删除属性,监听不到 —— 所有已 Vue.delete
// data.info.address = '上海' // 深度监听
data.nums.push(4) // 监听数组
解决方案——vdom
面试题:用JS模拟DOM元素
包含三部分:标签tag,附着在标签上的属性、样式、事件props,子元素children
通过snabbdom 学习vdom
h函数、vnode数据结构、patch函数
vdom总结
两个数做diff,如这里的vdom diff
vnode ->patch ->new vnode
树diff的时间复杂度O(n^3)
优化时间复杂度到O(n)
diff算法总结
with语法
模板编译
总结
vue中使用render代替template
总结
vue原理的三大知识点
组件渲染/更新过程
初次渲染过程
更新过程
触发setter,看是修改的data是否在getter中已经被监听,如果是,就执行render函数
patch的diff算法,会计算出最小差异,更新在DOM上
完整流程图
模板编译完,生成render函数,执行render函数生成vnode (虚拟DOM的树)
执行render函数的时候会touch getter,即执行函数的时候回触发Data里的getter
触发的时候就会收集依赖,即在模板中出发了哪个变量的getter就会把哪个给观察起来(watcher)
在修改Data的时候,看这个Data是否是之前作为依赖被观察起来的
如果是,就重新出发re-render,重新渲染,重新生成vdom tree,重新touch
异步渲染
1.$nextTick:
vue是异步渲染,$nextTick会待Dom渲染完之后调用
页面渲染时会将data的修改做整合,多次data修改只会渲染一次
2.汇总data的修改,一次性更新试图
3.减少DOM操作次数,提高性能
网页url组成部分
hash的特点
hash test
hash test
H5 history
history API test
history API test
总结
两者选择
to c的要是不需要管seo、搜索引擎也不需要用H5 history 简单一点就好