Vue【数据】数组操作

  例 子  

  定义数据结构,通过函数 data 返回数组 classmates,假设 classmates 数组中的每一个元素是班上的每一个同学的信息,然后通过 v-for 将每个同学的信息在页面上输出,p 是当前值,index 是当前索引。

<template>
    <div class="hello">
        <div v-for="(p, index) in classmates" :key="p.id">
            {{ `${index}.${p.name}` }}
        </div>
    </div>
</template>

<script>
export default {
    data(){
        return{
            classmates: [
                {id: 1, name: "许一"},
                {id: 2, name: "许二"},
                {id: 3, name: "许三"},
            ]
        };
    }
}
</script>
View Code

假如班上有一个同学转学了,同时,班上来了一个新同学。现在要修改代码。

下面是一个错误示范。圈起代码为新增代码。

假如许二转学走了,张三转学来了。尝试新增一个按钮,点击按钮之后调用 change 方法,更this.classmates[1] 。预想的页面效果是,点击按钮之后,“许二” 变为 “张三”。

<template>
    <div class="hello">
        <button @click="change">change</button>
        <div v-for="(p, index) in classmates" :key="p.id">
            {{ `${index}.${p.name}` }}
        </div>
    </div>
</template>

<script>
export default {
    data(){
        return{
            classmates: [
                {id: 1, name: "许一"},
                {id: 2, name: "许二"},
                {id: 3, name: "许三"},
            ]
        };
    },
    methods: {
        change(){
            this.classmates[1] = {id: 2, name: "张三"};
        }
    }
}
</script>
View Code

  上面修改数据失败的原因是,Vue 里的响应式依赖在 Vue2.0 版本里是通过 Object.defineProperty 实现的。在 Vue2.0 中,当我们把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。getter/setter 对用户是不可见的,但是在内部它们会让 Vue 能够追踪依赖,在属性变化和修改时进行通知,这也导致了 Vue 在操作时的一些局限性

( Vue 官网上的“ 如何追踪变化 ”部分 : https://cn.vuejs.org/v2/guide/reactivity.html#%E5%A6%82%E4%BD%95%E8%BF%BD%E8%B8%AA%E5%8F%98%E5%8C%96 )

局限性:

1. 不能检测对象属性的添加删除。对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。

2. 不能检测到数组长度变化(通过改变 length 而增加地长度不能监测到)。

3. 不是因为 defineProperty 的局限性,而是出于性能考量的,不会对每个元素都监听。因为对每个元素进行依赖跟踪都是有内存消耗和性能开销的,如果说数组是作为一个列表的遍历来使用的话,或者说数组是一个海量的数据的话,就会耗尽资源,会降低实用性,所以不会对每个元素都监听。在 Vue3 里使用 Proxy 来追踪依赖情况又会不同。

  数组操作 

Q: 如何操作数组中响应式的数据 ?

A: Vue 提供了 Vue.set 方法,向嵌套对象去添加响应式数据,还可以通过 this.$set 实例方法去添加属性,这是 Vue.set 全局方法的别名。删除的解决方案是通过 Vue.delete 或者实例上的 this.$delete 进行删除。

  例子  

实现点击 “ 添加新同学 ”按钮之后,页面上出现新同学的序号姓名。

<template>
    <div class="hello">
        <button @click="addClassmate">增加新同学</button>
        <div v-for="(p, index) in classmates" :key="p.id">
            {{ `${index}.${p.name}` }}
        </div>
    </div>
</template>

<script>
export default {
    data(){
        return{
            classmates: [
                {id: 1, name: "许一"},
                {id: 2, name: "许二"},
                {id: 3, name: "许三"},
            ]
        };
    },
    methods: {
        addClassmate(){
            this.$set(this.classmates, 3, 
                {id: 4, name: "张三"}
            )
        }
    }
}
</script>
View Code

通过 push 方法也能实现同样的页面效果。

<template>
    <div class="hello">
        <button @click="addClassmate">增加新同学</button>
        <div v-for="(p, index) in classmates" :key="p.id">
            {{ `${index}.${p.name}` }}
        </div>
    </div>
</template>

<script>
export default {
    data(){
        return{
            classmates: [
                {id: 1, name: "许一"},
                {id: 2, name: "许二"},
                {id: 3, name: "许三"},
            ]
        };
    },
    methods: {
        addClassmate(){
            this.classmates.push(
                {id: 4, name: "张三"}
            );
        }
    }
}
</script>
View Code

通过 push 方法也能实现同样的页面效果。因为在 Vue2.0 里对一些数组操作的方法进行了代理包装,在包装的实现里面把这些函数加入了响应式跟踪依赖,使用这些函数修改数据时会发生视图更新。

进行了代理包装处理的函数:push()、pop()、shift()、unshift()、splice()、sort()、reverse()

Prop&Data的笔记: https://www.cnblogs.com/xiaoxuStudy/p/12880361.html

计算属性和侦听器的笔记:https://www.cnblogs.com/xiaoxuStudy/p/13230664.html

原文地址:https://www.cnblogs.com/xiaoxuStudy/p/13230631.html