美文网首页
vue中的变化检测问题

vue中的变化检测问题

作者: frank_松 | 来源:发表于2020-03-17 22:19 被阅读0次

从vue通过Object.defineProperty方法劫持数据可知,vue是监听不到对象属性的增加或删除的,因为这些属性没有被劫持。想要监听数据变化,我们就要将其转换为响应式,这时候可以用this.$set(data, key, value)。

这个$set里面做了什么?

一、 给一个对象新增属性
我们将源码逻辑简化:

set(target, key, val) {
    ...
    const ob = target._ob_; // 获取对象的_ob_属性,它为劫持数据时创建的observer实例
    ...
    defineReactive(obj, key, val); // 通过definedReactive方法劫持属性,将其转换为响应式
    ob.dep.notify(); // 手动让发布者发送消息,通知订阅者进行更新
    return val;
}

二、给一个数组的一个位置添加元素

set(target, key, val) {
    ...
    if (Array.isArray(target)) { // 判断是数组
        target.length = Math.max(target.length, key); // 更新数组长度
        target.splice(key, 1, val); // 通过splice方法向数组指定位置插入元素
        return val;
    }
    ...
}

或许有人会问了,splice方法会改变原始数组,但是不改变数组在堆内存中的地址,为毛可以通过splice插入元素的方式触发订阅者更新?其实vue内部将数组原型中的方法篡改了,主要做了什么呢?

我们先列举出会改变原始数组的原型方法

const methods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'];

源码中依次遍历这些原型方法,改写其逻辑。主要是:首先获取原型方法执行后的返回值,然后通过数组的“ob”属性发出消息通知订阅者更新,然后将值返回。当使用splice,push,unshift这三个方法时,会额外对新增的元素做一次劫持。

由于原型方法已经被篡改了,只要使用这些方法修改数组,就会触发响应。

注:
1、直接修改数组某个索引的元素触发响应,arr[index] = newVal;
2、修改数组的长度length不会触发更新, arr.length = newVal;

相比大家也明白的原因,不在阐述。有问题请指出,谢谢!

相关文章

  • vue中的变化检测问题

    从vue通过Object.defineProperty方法劫持数据可知,vue是监听不到对象属性的增加或删除的,因...

  • Vue变化检测问题

    受现代 JavaScript 的限制(以及废弃 Object.observe),Vue 不能检测到对象属性的添加或...

  • Vue进阶学习笔记

    变化检测问题 Vue最显著的特性是响应式系统,修改模型层就会更新视图层。原理就是利用了Object.defineP...

  • vue vuex变化无法监听 解决方案和思路

    首选查阅官方文档 深入了解响应式编程 vue 变化检测原理使用 Object.defineProperty 把这些...

  • 图解VUE -- obj的变化检测

    由于是对vue源码的解析,文章中不可避免的会出现一些代码。但我经量会以图来解释obj的变化检测原理 对obj的变化...

  • vue 中的this问题

    在vue中当在vue中使用匿名函数的时候,会出现this指针改变的问题,出现方法或者属性数据undefine的问题...

  • (十)Vue中的is和操作DOM

    本节知识点 Vue 中的is 问题 (1) Vue中的is属性 vue中is的属性引入是为了解决dom结构中对放入...

  • Vue3.0破坏性变化----Global API改为应用程序实

    vue2中有很多全局的api可以改变vue的行为,比如Vue.component等,这导致一些问题: vue2中没...

  • Vue中this指向的问题

    我们知道,如果Vue的data中有属性message,那么方法中直接用this.message就可以获取到这个me...

  • vue中this的指向问题

    在函数中需要遍历数组等对象时,遍历中的this会指向window,所以需要在遍历前定义一下this指向

网友评论

      本文标题:vue中的变化检测问题

      本文链接:https://www.haomeiwen.com/subject/cwnzehtx.html