review vue.js 官方文档

一、数组的变异(数组更新)

Vue.js 内部对被观察数组的变异方法 (mutating methods,包括 push() , pop() , shift() , unshift() , splic
e() , sort() 和 reverse() ) 进行了拦截,因此调用这些方法也将自动触发视图更新。

// 以下操作会触发 DOM 更新
demo.items.unshift({ childMsg: 'Baz' })
demo.items.pop()

无论是变异数组或是非变异数组,当数组值改变的时候,地址指针都不会改变。而 vue 是一个以数据驱动的框架,当数组值变化的时候,自然希望依赖于变化数据的视图也触发更新。用过 vue 的小伙伴都知道,当数组改变的时候,视图也更新了。那 vue 帮我们做了什么事情呢,就让我们深入源码一探究竟吧。
// vue 2.6  
// src/core/observer/array.js
const arrayProto = Array.prototype; // 获取数组原型对象
const arrayMethods = Object.create(arrayProto); // 生成一个新对象,且__proto__ 指向 数组原型对象
const methods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'];

/**
 * Intercept mutating methods and emit events
 */
methods.forEach(method => {
    const original = arrayProto[method]; 
    let val = function mutator (...args) {
        const result = original.apply(this, args); //缓存原始方法
        let inserted = null;
        switch (method) {
            case 'push':
                inserted = args;
                break;
            case 'unshift':
                inserted = args;
                break;
            case 'splice':
                inserted = args.slice(2); // array.splice(start[, deleteCount[, item1[, item2[, ...]]]]) [item])
                break;
        }
        if (inserted) observeArray(inserted); // 获取插入的值,并设置响应式监听
        notify(); // 通知依赖像更新
        return result;
    }
    
    Object.defineProperty(arrayMethods, method, {
        value: val,
        writable: true,
        configurable: true,
        enumerable: true
    })
})

const observeArray = function observeArray (inserted) { // 简写,[具体实现](https://github.com/vuejs/vue/blob/2.6/src/core/observer/index.js)
    console.log(inserted); //新增的元素形成的数组
    console.log('响应式监听数组');
}

const notify = function notify () {
    console.log('视图更新了');
}

在Vue现有阶段中,对响应式处理利用的是Object.defineProperty对数据进行拦截,而这个方法并不能监听到数组内部变化,数组长度变化,数组的截取变化等,所以我们需要对这些操作进行hack,让vue能监听到其中的变化。

上一篇:Java中PhantomReference、WeakReference、SoftReference有什么区别?


下一篇:聊聊服务稳定性保障这些事