页面渲染时出现的问题

142 阅读2分钟

数据更新时的一个问题

问题演示:数据发生了改变,但是页面并没有渲染新的数据

<body>
    <div id="app">
        <div v-for="el in person">
            <p>{{el.name}}</p>
            <p>{{el.age}}</p>
        </div>
        <div>
            <button @click="update">修改第一个人名信息</button>
        </div>
    </div>
    <script>
        new Vue({
            el:"#app",
            data:{
                person:[
                    {id:1,name:"jessic",age:33},
                    {id:2,name:"hyomin",age:33},
                    {id:3,name:"gloria",age:31},
                ]
            },
            methods: {
                update(){
                    this.person[0]={id:1,name:"tangxika",age:3};
                    console.log(this.person[0],111);
                }
            },
        })
    </script>

image.png

Vue监测数据的原理

1.Vue会通过Object.defineProperty()来劫持data中各个属性的setter,getter,但是不会劫持数组的下标。

2.对象中的数据通过setter实现监视且在创建VM对象时就传入要监测的数据。对象中后追加的属性,Vue默认不做响应式处理,若需要给后添加的属性做响应式需要使用提供的API触发视图更新。

3.数组中的数据监测通过包装数组更新元素的方法,包装时先调用原生对应的方法对数组进行更新,然后重新解析模板进而刷新页面。

Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()
  • filter()concat() 和 slice()。它们不会改变原始数组,但总是返回一个新数组。当使用非变更方法时,可以用新数组替换旧数组

解决方法:Vue.set(),第1个参数是要操作的对象,第2个参数就是要改变的数组下标或对象的属性名,第3个参数是改变的值。或者创建的Vue组件中使用this.$set(),参数同理。

  • 参数

    • {Object | Array} target
    • {string | number} propertyName/index
    • {any} value
  • 返回值:设置的值。

  • 用法

    • 向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新。它必须用于向创建VM对象时就传入的对象上添加新属性,因为 Vue 无法探测新增对象的属性

ps:注意目标对象不能是 Vue 实例,或者 Vue 实例的根数据对象,必须是Vue 实例中已有的对象