Vue中$set方法

项目场景:

例如:在我写前端项目的时候,后端给我们的一个json对象,并且我已经渲染在页面上了。但是由于我自己的需求,想往返回的对象里面添加一个字段,后来才意识到不是响应式的。如果我们要让这个新字段是响应式的,就要使用到this.$set来注入数据。

当vue的data里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)时,向对象中添加新的属性,如果更新此属性的值,是不会更新视图的。

问题描述:

话不多说,上demo:

<!--先看一个例子-->

<template>
  <div class="hello">
   <div>{
    
    {list}}</div>
    <button @click="add">age++</button>
  </div>
 
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      list: {name:'LL'}
    }
  },
  methods:{
    add(){
      if(!this.list.age){
        this.list.age=18
      }else
      {
        this.list.age++
      }
       console.log(this.list)
    }
  }
}
</script>
<style scoped>

</style>

当我们没有使用this.$set去添加对象属性时,效果图如下:

新属性age确实已经添加,但页面list并未重新渲染到视图层上,页面并没有响应式的渲染age属性

当我们使用了this.$set来添加对象属性:

    add() {
      if(!this.list.age){
        this.$set(this.list,'age',19)
      }else{
        this.list.age++
      }
       console.log(this.list)
    },

我们可以发现这时候添加的数据就变成响应式数据了。


原因分析:

由于 Vue 会在初始化实例时进行双向数据绑定,使用Object.defineProperty()对属性遍历添加 getter/setter 方法,所以属性必须在 data 对象上存在时才能进行上述过程 ,这样才能让它是响应的。如果要给对象添加新的属性,此时新属性没有进行过上述过程,不是响应式的,所以会出想数据变化,页面不变的情况。此时需要用到$set。
向响应式对象中添加一个 property,并确保这个新 property 同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新 property,因为 Vue 无法探测普通的新增 property
(比如 this.myObject.newProperty = ‘hi’)

Vue 无法检测 property 的添加或移除。由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的。例如:

var vm = new Vue({
  data:{
    a:1
  }
})

// `vm.a` 是响应式的

vm.b = 2
// `vm.b` 是非响应式的

解决方案:

使用:

Vue.set( target, propertyName/index, value )
参数:

{Object | Array} target
{string | number} propertyName/index
{any} value
返回值:设置的值
数组: this.$set(Array, index, newValue)
注意:这里数组使用的是通过索引来修改会替换值。
对象: this.$set(Object, 'Key', Value)
注意:这里对象是通过键名来进行修改和操作,所以需要用sting格式。

补充:

有时你可能需要为已有对象赋值多个新 property,比如使用 Object.assign() 或 _.extend()。但是,这样添加到对象上的新 property 不会触发更新。在这种情况下,你应该用原对象与要混合进去的对象的 property 一起创建一个新的对象。

// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })

猜你喜欢

转载自blog.csdn.net/m0_60237095/article/details/129142631