如何理解Vue的数据响应式

152 阅读1分钟

什么是响应式?

响应式就是一个物体可以对于外界的刺激作出反应,那么我们就说这个物体是响应式的。类似于我打你一拳,你感觉疼,你对于我的一拳做出了反应,你也是响应式的。

Vue的数据响应式

就是数据发生变化的时候,页面的UI也会跟着刷新。 举个栗子:

const vm = new Vue({
    el: '#app',
    data: {
        name: 'Carlos'
    }
})

根据上面的代码,页面上会显示的是Carlos,如果执行vm.name = Nancy,则会由Carlos变成Nancy。

以上是正常情况,但是也有一些变态的情况。

  1. 当data为空对象的时候,Vue会给出警告,如下:
new Vue({
    data:{},
    template:`
        <div>{{n}}</div>
    `
}).$mount('#app');

1632225501(1).jpg

  1. 当data为a,却要在页面上显示b的时候,会出现警告。因为Vue只检查第一层,所以这个警告可以消除。
new Vue({
    data:{
        obj:{
            a:0 //obj.a会被Vue监听和代理
        }
    },
    template:`
        <div>
            {{obj.a}}
            <button @click="setB">set b</button>
        </div>
    `,
    methods:{
        setB(){
            this.obj.b = 1
        }
    }
}).$mount("#app")

1632225864(1).jpg 在这里点击setb的按钮是没法出现1的。因为Vue没有办法监听一开始不存在的obj.b。

解决办法

  1. 提前把所有的key都声明好,即使是空值。
new Vue({
   data: {
     obj: {
       a: 0 // obj.a 会被 Vue 监听 & 代理
       b: undefined
     }
   },
   template: `
     <div>
      {{obj.b}}
      <button @click="setB">set b</button>
    </div>
  `,
  methods: {
    setB() {
      this.obj.b = 1; 
    }
  }
}).$mount("#app");

1632226296(1).jpg 再次点击set b按钮之后,就会出现1了。

  1. 使用Vue.set或者this.$set
new Vue({
   data: {
     obj: {
       a: 0 // obj.a 会被 Vue 监听 & 代理
       b: undefined
     }
   },
   template: `
     <div>
      {{obj.b}}
      <button @click="setB">set b</button>
    </div>
  `,
  methods: {
    setB() {
      Vue.set(this.obj, 'b', 1); //也可以写成this.$set(this.obj,'b',1)
    }
  }
}).$mount("#app");

data中有数组应该怎么办? 因为数组的长度可以一直增加,所以没有办法使用第一种办法——将所有key都声明好,每次修改数组,都要添加Vue.setthis.$set也很麻烦。

所以可以使用Vue的数组变异方法中的push

    new Vue({
        data:{
            array:["a","b","c"]
        },
        template: `
     <div>
      {{array}}
      <button @click="setD">set d</button>
    </div>
  `,
  methods:{
      setD(){
          this.array.push("d")
      }
  }
  
  }).$mount("#app");

1632226873(1).jpg

尤雨溪篡改了数组的7个API,调用之后会更新UI,具体使用方法可以查看文档中的[变异方法](列表渲染 — Vue.js (vuejs.org))。

1632227263(1).jpg