vue数组更新后,页面没有动态刷新的问题

在一个函数中,改变了data中的数据,在函数中查看是修改成功的,但是页面中并没有刷新。

尤大的解释:由于性能的代价与获得的用户体验不成正比,故vue2.0的实现中放弃了这个特性。在vue3.0中,使用proxy替代了Object.defineProperty()

数组变更检测注意事项:

由于JS的限制,以下两种情况,vue不能检测以下数组的变动

  1. 当利用索引直接修改数组的某一项时
  2. 直接修改数组的长度时

示例:

var vm = new Vue({
  data: {
    items: ['a', 'b', 'c']
  }
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的

也就是说,直接设置数组的某一项时,虽然改变了数组的值,但视图上显示的仍然为数组之前的值,数据的响应式失效了。

vue的数据劫持是利用Object.defineProperty()get,set方法,但是get,set是有限制的。示例:

var person = {};
Object.defineProperty( person, { 
      age: { 
        defaultValue: 11, 
        get: function () {
          return this.defaultValue;
        }, 
        set: function (val) { 
          this.defaultValue = val; 
          console.log("触发了set") 
        }
      } 
    });
 
// 修改属性的值时能够触发set
person.age = 12    // 触发了set
->触发了set
->12
 
person.age
->12
 
// 将属性的值设置为一个数组,当通过索引值修改数组的某一项或使用数组的某些方法修改数组时不能触发set
person.age = [2,3,4]    // 触发了set
->触发了set
->(3) [2, 3, 4]
 
person.age[2] = 5      // 未触发set
->5
 
person.age
->(3) [2, 3, 5]
 
person.age.push(5)     // 未触发set
->4
 
person.age
->(4) [2, 3, 4, 5]
 
 
// 将属性的值设置为一个对象,当修改对象中某属性的值时无法触发set
person.age = { first: 1 }
->触发了set
->{first: 1}
 
person.age.first = 2      // 未触发set
->2

通过上述例子可以观察得出:

当该属性的值为一个数组时,通过索引修改数组某一项的值或使用数组的某些方法修改数组并不能触发set;当属性的值为一对象时,直接修改对象中属性的值时也无法触发set。

解决方法:

  1. Vue.setVue.set(vm.items, indexOfItem, newValue)
  2. vm.$set(vm.items, indexOfItem, newValue)也可以使用 vm.$set 实例方法,该方法是全局方法 Vue.set 的一个别名
  3. vm.items.splice(indexOfItem, 1, newValue)
  4. 运用this.$forceUpdate()强制刷新。
    示例:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <ul>
            <li v-for='(item,index) in list' :key='index'>{{item}}</li>
        </ul>
        <button @click='change'>按钮</button>
    </div>
</body>
</html>
<script src="./lib/vue-2.6.10.js"></script>
<script>
    var vm = new Vue({
        el:'#app',
        data:{
            list:[
                1,2,3,4,5
            ]
        },
        methods: {
            change(){
                this.list[0] = 2
                // Vue.set(vm.list,0,2)
                vm.list.splice(0,1,2)
                // this.$forceUpdate()
                console.log(this.list);
            }
        },
    })
</script>

proxy

  1. Object.define()只能对属性进行劫持,需要遍历对象的每个属性,若属性值也是对象,则需要深度遍历。而Proxy直接代理对象,不需要遍历操作。
  2. 新增属性时,需要重新遍历对象,对其新增属性在使用Object.define()进行劫持。
    参考链接:

VUE中数组更新后,页面没有动态刷新问题
vue为什么不能检测数组的变化

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容