Vue源码学习之$set实现原理

前言

 在Vue2中当我们通过数组的下标去修改数组值,或者向对象添加添加属性时,对应的视图都无法进行更新,这是因为我们所添加的数据不是响应式的,无法响应视图的变化。那么此时我们可以通过$set来实现。对于数组可以通过this.$set(this.arr,0,‘xx’)来去修改数组下标对应的值,对于对象可以通过this.$set(this.obj,‘a’,‘xxx’)向对象新增属性a,接下来我们来根据源码来分析原理。

源码分析

 源码如下:

        if (isUndef(target) || isPrimitive(target)) {
    
    
            warn(("Cannot set reactive property on undefined, null, or primitive value: " + ((target))));
        }
        // 判断是否为数组,并判断key是不是有效索引,
        if (Array.isArray(target) && isValidArrayIndex(key)) {
    
    
            // 判断下标和数组长度,将数组的.length属性设置为最大值
            target.length = Math.max(target.length, key);
            // 调用数组的splice方法,将修改的数据变为响应式
            target.splice(key, 1, val);
            // 返回对应的val
            return val
        }
        // 如果这个属性在这个对象上,则设置属性为对应的属性值后直接返回val
        if (key in target && !(key in Object.prototype)) {
    
    
            target[key] = val;
            return val
        }
        // 获取响应式对象__ob__
        var ob = (target).__ob__;
        // 判断当前的目标对象是否是Vue实例,或者根数据对象,如果是则warn警告并返回
        if (target._isVue || (ob && ob.vmCount)) {
    
    
            warn(
                'Avoid adding reactive properties to a Vue instance or its root $data ' +
                'at runtime - declare it upfront in the data option.'
            );
            return val
        }
        // 当前的这个目标对象如果不是响应式对象则直接赋值返回
        if (!ob) {
    
    
            target[key] = val;
            return val
        }
        
        // 给目标对象对应的属性添加响应式
        defineReactive$$1(ob.value, key, val);
        // 通知所有订阅者,调用update,更新渲染视图
        ob.dep.notify();
        return val

 源码分析如下:
 当$set所设置的目标对象为数组时,则调用目标对象的splice方法将修改的数据变为响应式。
 当$set所设置的目标对象为对象时,首先判断这个属性是否在这个对象上,如果存在则设置属性为对应的属性值后直接返回val,然后判断目标对象是否为Vue实例或者根数据对象,如果是则warn警告后返回,再去判断这个目标对象是否是响应式的,如果不是响应式对象则直接赋值返回。最后在给目标对象的属性添加响应式,通知dep实例的所有订阅者进行更新。

猜你喜欢

转载自blog.csdn.net/liu19721018/article/details/125554525
今日推荐