1. MVVM原理
vue的精髓在于组件化和数据驱动视图。
- 组件化之前就有,比如php等语言,vue使用了组件化思想。
- 进行了数据驱动视图的创新。之前的前端操作是静态渲染,要操作dom修改视图。
数据劫持的优势
- 无需显示调用,直接通知变化并驱动视图,react需要显示调用setState。
- 可精确得知变化数据,减少diff的额外开销。
data监听原理
Vue2核心api:Object.defineProperty
- 无法原生监听数组变化,vue对数组常用的8种方法进行hack,不过其他方法无法监听。
- 深度遍历时,一次性计算量大。
- 无法监听新增/删除属性,需在实例 data 声明所有响应值。删除设置为 null 即可。
具体实现
// 在html中引入,修改data的值即可看到效果
// 触发更新视图
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