目录
vue源码系列之 响应式数据处理2 数组的重写
vue源码系列之 响应式数据处理1 链接: link.
array.js
- 对数组的方法进行重写
- oldArrayPrototype 原始的数组方法
- arrayMethos = Object.create(oldArrayPrototype) 创建一个新的对象,也就是拷贝原始数组的方法
- methods 中的方法,是会影响原始数组的,因此需要重写这些方法
- 遍历这些会改原始数组的方法,然后执行步骤是
- 先执行自己定义的arrayMethos 方法,之后再调用原始数组的方法
- 其中最主要的是:假如args传入的实参为 对象时候 则需要特殊处理
- inserted 为新增要插入的数据( [ [1,2,3] , {name:“ppp”} ] )类似这种需要特殊处理
- 然后假设有新增数据时,则需要继续劫持,观测数组里面的每一项数据
let oldArrayPrototype = Array.prototype;
export let arrayMethos = Object.create(oldArrayPrototype);
let methods = [
'push',
'shift',
'unshift',
'pop',
'reverse',
'sort',
'splice'
]
methods.forEach(method => {
arrayMethos[method] = function (...args) {
oldArrayPrototype[method].call(this, ...args);
let inserted;
let ob = this.__ob__;
switch (method) {
case "push":
case "unshift":
args;
case "splice":
args.slice(2)
default:
break;
}
if (inserted) ob.observeArray(inserted);
}
})
observe / index.js
- 作用:观察者监听数据的变化,实现数据的响应式
- 执行流程:
- Observer观察者之内首先判断是对象还是数组
- 是对象的时候,则是执行 walk() 方法,对对象属性的劫持,转化为响应式属性
- 其中转化为响应式属性是采用
Object.defineProperty 方法 - 值得注意的是:若是设置新值时,为对象,则需要继续监听
- 因此对于
data.__ob__ 属性,则需要设置为不可枚举,否者会陷入死循环 - 为数组的时候:
- 拿到重写的方法,赋值给当前对象的属性,也就是重写的方法
- 值得注意的是:数组内含有数组或者对象时候,又需要针对数组进行监听
this.observeArray(data); - observeArray(data)遍历数组中的每一项,然后进行观测
observe(item) - 引入 数组重写的方法 arrayMethos
import {
arrayMethos
} from "../array";
import {
isObject
} from "../utils";
class Observer {
constructor(data) {
Object.defineProperty(data, '__ob__', {
value: "this",
enumerable: false,
})
if (Array.isArray(data)) {
data.__proto__ = arrayMethos;
this.observeArray(data);
} else {
this.walk(data);
}
}
observeArray(data) {
data.forEach(item => {
observe(item)
})
}
walk(data) {
Object.keys(data).forEach(key => {
defineReactive(data, key, data[key]);
})
}
}
function defineReactive(data, key, value) {
observe(value);
Object.defineProperty(data, key, {
get() {
return value;
},
set(newVal) {
observe(newVal)
value = newVal;
}
})
}
export function observe(data) {
if (!isObject(data)) {
return;
}
if (data.__ob__) {
return;
}
return new Observer(data)
}
|