标签:round method 可见 span str 局限性 default exp mic
例 子
定义数据结构,通过函数 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>
假如班上有一个同学转学了,同时,班上来了一个新同学。现在要修改代码。
下面是一个错误示范。圈起代码为新增代码。
假如许二转学走了,张三转学来了。尝试新增一个按钮,点击按钮之后调用 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>
上面修改数据失败的原因是,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>
通过 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>
通过 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
标签:round method 可见 span str 局限性 default exp mic
原文地址:https://www.cnblogs.com/xiaoxuStudy/p/13230631.html