vue中修改对象数组的属性值不会渲染到页面上

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue中修改对象数组的属性值不会渲染到页面上相关的知识,希望对你有一定的参考价值。

参考技术A tableData是一个对象数组
逻辑:点击修改按钮 触发modifyStrategy方法 修改tableData数组对应下标的对象的属性值

console.log属性值确实修改了,但是没有更新视图

原因:

查到是因为vue实现双向数据绑定的机制是数据劫持,也就是在所有对象上有个Object.defineProperty()方法,通过监听set,get方法去实现,而数组没有这两个方法,所以就不会更新view;解决方案就是,需要我们主动通知vue

解决:

增加this.$set()

Vue2源码解读

Vue2源码解读 - $set()使用及实现原理

  • 当我们给响应式的对象新增属性时,新增的属性并不会渲染到页面中
  • 对于响应式的数组,增加元素、修改数组长度时,数组的这些变化也不会反映到页面中

那么如何让新增的对象或数组实现响应式及时渲染页面呢?

使用this.$set()

官方定义

Vue 不允许在已经创建的实例上动态添加新的根级响应式属性 (root-level reactive property)。然而它可以使用 Vue.set(object, key, value)方法将响应属性添加到嵌套的对象上

// Vue.set(object, key, value) 
<template>
    <div>{{obj.k}}</div>
</template>
<script>
export default {
    data() {
        return {
            obj: {
                s: \'1\',
                z: \'2\'
            }
        }   
    },
    mounted() {
        this.$set(this.obj, \'k\', \'3\')
    }
}
</script>

$set原理

直接看源码

function set(target: Array<any> | Object, key: any, val: any): any {
  // isUndef 是判断 target 是不是等于 undefined 或者 null 。
  //isPrimitive 是判断 target 的数据类型是不是 string、number、symbol、boolean 中的一种
  if (process.env.NODE_ENV !== \'production\' &&
    (isUndef(target) || isPrimitive(target))
  ) {
    warn(`Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}`)
  }

  // 数组的处理
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    target.length = Math.max(target.length, key)
    target.splice(key, 1, val)
    return val
  }

  // 对象,并且该属性原来已存在于对象中,则直接更新
  if (key in target && !(key in Object.prototype)) {
    target[key] = val
    return val
  }

  // vue给响应式对象(比如 data 里定义的对象)都加了一个 __ob__ 属性,
  // 如果一个对象有这个 __ob__ 属性,那么就说明这个对象是响应式对象,我们修改对象已有属性的时候就会触发页面渲染。
  // 非 data 里定义的就不是响应式对象。
  const ob = (target: any).__ob__

  if (target._isVue || (ob && ob.vmCount)) {
    process.env.NODE_ENV !== \'production\' && warn(
      \'Avoid adding reactive properties to a Vue instance or its root $data \' +
      \'at runtime - declare it upfront in the data option.\'
    )
    return val
  }

  // 不是响应式对象
  if (!ob) {
    target[key] = val
    return val
  }

  // 是响应式对象,进行依赖收集
  defineReactive(ob.value, key, val)

  // 触发更新视图
  ob.dep.notify()
  return val
}

以上是关于vue中修改对象数组的属性值不会渲染到页面上的主要内容,如果未能解决你的问题,请参考以下文章

vue改变数组或者对象的某一项,页面视图没有渲染

Vue方向:Vue实例上使用$set()更新对象或数组

关于vue数组中对象属性变更页面没重新渲染的问题

vue的watcher 关于数组和对象

vue数组中对象属性变化页面不渲染问题

vue数组中对象属性变化页面不渲染问题