provide vue 响应式_Vue数据响应式

本文探讨Vue的响应式机制,通过Object.defineProperty实现数据变化的追踪。详细介绍了当对象属性未定义、数组操作时遇到的问题及解决方案,如Vue.set和this.$set的使用,以及Vue如何对数组的特定方法进行优化以确保视图更新。同时,阐述了Vue对数组变更方法的包裹,确保数组操作后的视图同步。
摘要由CSDN通过智能技术生成

ad2046e0edebbdd053d91a095e3919ee.png

目录:

1.什么是响应式?

2.Object.defineProperty存在的问题以及解决方案

3.data中有数组怎么办

4.Vue下的数组的变更方法


1.什么是响应式?

我打你一拳,你喊疼,你就是响应式的

const vm = new Vue({data: { n : 0 } })

Vue的data是响应式的

体现在,如果修改vm.n,那么UI中的n就会做出响应

Vue2通过Object.defineProperty来实现数据响应式

2.Object.defineProperty存在问题

一般情况下,

Object.defineProperty(obj,'foo',{
    value : 100
})
//函数参数列有:对象名,属性名,属性值

特殊情况1:data中不定义foo,在tamplate调用foo

new Vue({
  data: {},             //这里没有定义foo
  template: `
    <div>{{foo}}</div>   //这里又调用n
  `
}).$mount("#app");
​
[Vue warn]: Property or method "foo" is not defined on the instance but referenced during render.
//此时控制台会输出一段警告,表明你没有定义foo但是渲染时却又调用

特殊情况2:

Vue只检查属性的第一层 { 这里面写了就行 }

data中不定义属性b,methods中对属性b进行操作

new Vue({
  data: {   //第一层
    obj: {  //第二层
      a: 0  // obj.a 会被 Vue 监听 & 代理
           // 此时不定义b
    }
  },
  template: `
    <div>
      {{obj.b}}         //这里调用obj.b
      <button @click="setB">set b</button>
    </div>
  `,
  methods: {
    setB() {
      this.obj.b = 1; //请问,页面中会显示 1 吗?
    }
  }
}).$mount("#app");
​
//此时,控制台并不会报错。但是,点击button页面也不会有反应
//Vue没办法监听一开始不存在的obj.b

解决办法:

Vue.set(vm.someObject, 'price_one', 666)
​
this.$set(this.someObject,'price_two',999)
​
//两者等价

作用:

1.新增key

2.自动创建代理和监听(如果没有创建过)

3.触发UI更新(但不是立刻)

3.继续特殊情况:data中有数组怎么办?

new Vue({
  data: {
    array: ["a", "b", "c"]
  },
  template: `
    <div>
      {{array}}
      <button @click="setD">set d</button>
    </div>
  `,
  methods: {
    setD() {
      this.array[3] = "d"; //请问,页面中会显示 'd' 吗?
      // 等下,你为什么不用 this.array.push('d')
    }
  }
}).$mount("#app");
​
//点击之后毫无反应
//data中的数组等同于
{
    {0:'a',1:'b',2:'c'}
}
//所以此时添加d,但是与"特殊情况1" 中相同,d没有下标,所以无法追加到数组中

问题来了:只能用Vue.set或者this.$set了吗?

 methods: {
    setD() {
      this.$set(this.array,3,'d')
    }
  }
//这样确实可以运行,但是js操作数组时一般用push来追加元素

等下,你为什么不用 this.array.push('d')

 methods: {
    setD() {
      this.array.push('d')
      //console.log(this.array)
    }
  }
//成功了,此时控制台输出this.array

62c18aa18e7a8490f70ee7bf6f577f34.png

此时,数组的方法已经不是js中数组自带的方法,vue对它进行了升级

大致思路为(以push方法为例)

class VueArray extends Array{
    push(...args){
        const oldLength = this.length   //this代表当前数组
        super.push(...args)
        console.log('你进行了push')
        for(let i = oldLength ;i<this.length; i++){
            Vue.set(this, i ,this[i])
            //将每个新增的key都告诉Vue
        }
    }
}

4.查阅文档发现,Vue对如下几个方法都进行过了升级

//位置:数组更新检测-变更方法
Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:
​
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值