Vue.js

Vue data中属性不响应及解决方法

2019-04-26  本文已影响0人  简人Lmy

现在vue框架用起来虽然很方便,很爽,但是难免也会遇到一些问题,其中新手遇到的data属性更改了但却没有刷新界面,即不响应的问题是比较烦人的,下面我就介绍一下,为vue新手的起步之路扫除一个障碍🙂。

给vue实例添加属性一般有两种方式。

  1. 直接写在data里面

data() {
          return {
                   name:''
                 }
        }
  1. data中没有age属性

      vm.age = 26

对于这两种情况,第一种的name是响应的,而第二种的age无法响应。为什么呢,我们再解释下是否响应是怎么来的,即vue给属性添加响应关系的过程是怎样的。

vue会在vue实例初始化的时候对data中的属性执行getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它。

很明显,第二种的age错过了添加getter/setter转化的时机,所以无法响应。

不过我相信大多数人遇到问题的都不是这种,而是第一例的另一种情况,我直接上部分代码:

data()  {
      return {
          person:{}
             }
},
methods:{
      btnPressed():{
          this.person.name = '张三'
     }
}

这种情况的话,personname确实是被改成了'张三',相信你也log了好几次,但是为什么界面上就是没有更改呢,原因刚才已经说过了,因为这里的name并未添加getter/setter的监测方法,即无法响应,当这个name的值改变的时候,界面上无法进行相应的更改,那有些人可能会说我这个person不是响应的吗?
没错,person是响应的,但这里的person是个对象,对person添加getter/setter转化方法时,person还没有name这个字段,所以person可以响应,而person.name无法响应。

推测

data中的对象类型的属性,如果在data中已写出,就会被添加getter/setter方法进行响应式监测处理,而没有写的则不会,查了很多资料,好像也确实是这个道理,如以下这个例子。

<template>
  <div id="app">
    <div>{{person.name}}</div>
    <div>{{person.age}}</div>
    <button @click="btnPressed">点击</button>
  </div>
</template>

<script>
export default {
  name: 'app',
  data(){
    return {
      person:{name:''}
    }
  },

  created(){
    this.person.name = 'liu'
    this.person.age = '100'
  },
  methods:{
    btnPressed(){
      this.person.name = 'zhao'
      this.person.age = '200'
    }
  }
}
</script>

根据推测,界面上应该一开始出现'liu''100'两行,但是点击了按钮执行btnPressed之后,第一行会变为'zhao',而第二行不变,还是'100'

但是!!结果两个值都变了,第二行也变为了'200',之后我又加了各种属性,gender,father等,依然都跟着改变,只要person中有其中一个初始值,它的所有属性就都会变成响应式;
然而,将person的属性key由'name'改为'names',那么这里的nameage都不会被改变,也就是后面我修改的任意属性值又不是响应式了......不信的可以试试,我这里还没有理解😅,求大神给解释。

解决方案

这里首先给出官方的解决方案:

    this.$set(this.person,'name','zhao')

这句话加上之后如果this.personname属性没有setter/getter响应方法,则会添加上,属性为响应式。你可能以为这样就可以了,然而事实还是在执行方法时name属性没有改变🤔,因为我们是把它放在按钮点击方法里的,所以最开始不会执行这个地方,我们找找。

问题在这里

  created(){
    this.person.name = 'liu'
    this.person.age = '100'
  },

由于这里是第一次给person添加name属性,也没有使用$set方法,所以name这里没有settergetter方法,而后面再用$set方法的时候,由于name属性已存在了,所以$set方法不会再进行setter/getter方法进行响应式监测,这里一定要注意。

结论:

还是要细读官方文档,vue作者已经在其中推荐尽量在data初始化中将需要用到的属性都写出来,这样便于维护且可读性更好。
如果data中某属性对应初始值为{},且依然想要添加响应式属性的话,用以下方法:
      this.$set(this.objectProperty,'key',value)
注意第一次添加该属性一定要用此方法,之后则可以直接用点语法赋值而该属性依然为响应式属性;若第一次用点语法赋值,第二次及以后再用$set方法的话则该属性为非响应式。
上一篇下一篇

猜你喜欢

热点阅读