Vue中关于数组与对象修改触发页面更新的机制与原理简析
Vue中关于数组与对象修改触发页面更新的机制与原理简析
相关问题
数组
使用索引直接赋值与直接修改数组length时,不会触发页面更新。
例如:
<script>
export default {
name: "HomeView",
data: () => ({
list1: ["A", "B"],
}),
methods: {
btnClicked() {
this.list1[0] = "C"
this.list1[2] = "C"
},
},
}
</script>
或是
<script>
export default {
name: "HomeView",
data: () => ({
list1: [{ text: "123" }, { text: "456" }],
}),
methods: {
btnClicked() {
this.list1[0] = { text: "789" }
},
},
}
</script>
页面并不会触发更新。
对象
页面初始化完成后,在方法中直接对data内声明对象当前不存在的属性进行赋值来为对象新增属性时,页面也不会响应渲染。
例如:
<script>
export default {
name: "HomeView",
data: () => ({
obj1: { a: "a", b: "b" },
}),
methods: {
btnClicked() {
this.obj1.c = "c"
},
},
}
</script>
页面并不会触发更新。
原因
Vue在初始化时会将data内所有的属性嵌套遍历并重写其Getter和Setter方法,借此实现响应式属性。
然而对于在页面渲染完成后加入data的属性,Vue并不会将其变为响应式。
一些深入的探究
数组
Vue对于数组是仅将其对应下标的对象的属性变为响应式,而这个下标本身是无法成为响应式的。
data: () => ({
list1: [{ text: "123" }, { text: "456" }],
})
使用如上的data声明。
方法A:
this.list1[0] = { text: "789" }
方法B:
this.list1[0].text = "789"
方法B可以被正确响应而方法A不可以。
方法A将数组下标为0的位置替换为了一个新的对象,而因为数组下标不是响应式的,因此没有触发页面刷新。
同时,由于数组下标为0的位置替换为了一个新的对象,而这个新的对象并没有被配置为响应式,那对于这个对象属性的修改也不会触发页面更新。如下:
this.list1[0] = { text: "789" }
this.list1[0].text = "456"
由于新的对象的属性并没有被配置为响应式,那么即使对这个对象的属性进行修改,页面也不会被更新。
既然下标本身无法成为响应式,不妨尝试:
<script>
export default {
name: "HomeView",
data: () => ({
list1: ["A", "B"],
}),
methods: {
btnClicked() {
this.list1[0] = "C"
},
},
}
</script>
通过下标修改数组的对应值也无法触发视图更新。
对象
data: () => ({
obj1: { a: { text: "a" }, b: { text: "b" } },
}),
使用如上的data声明。
this.obj1.a = { text: "c" }
成功触发视图更新。
与数组下标不同,对象的属性在初始化是被定义为响应式的,因此直接对属性赋值对象是能够触发视图更新的。不像对数组的对应下标赋值而不会触发视图更新。
解决方案
数组
1. 内置API
如果需要向数组加入新的成员,则可以直接使用数组的push方法。
此外,下列数组方法也可以自动的触发视图刷新:
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
2. 将数组重新赋值,修改引用地址
为数组新增一个字符串成员"C"
this.list1 = this.list1.concat(["C"])
由于list1是data的属性,list1的引用发生改变,就会触发视图更新。
修改数组的第一个值
let tempList = this.list1.concat([]) // 深拷贝,等价于一个新数组,使用slice,JSON都可以。
tempList[0] = "666"
this.list1 = tempList
通过原数组新建一个新数组,修改新数组后再将新数组赋值给原数组,由于原数组作为data的属性,其引用被修改,触发视图更新。
3. Vue.$set() 方法
使用Vue.$set可以为data对象添加一个新的响应式属性,且触发视图更新。
定义:
Vue.$set(对象或数组, 对象属性名或数组下标, 值)
向list1对象的0索引位置赋值一个新的响应式对象,同时触发视图更新:
Vue.$set(this.list1, 0, { text: "789" })
如果在组件中应使用this.$set来代替:
this.$set(this.list1, 0, { text: "789" })
对象
1. 将对象重新赋值,修改引用地址
思路与数组的类同。
使用JSON、手写递归、lodash深拷贝均可,但如果对象内含方法,则不能使用JSON来完成深拷贝。
深拷贝完成后修改对应属性后赋值给原对象即可。
2. Vue.$set() 方法
对象同样可以使用$set() 方法修改。
定义:
Vue.$set(对象或数组, 对象属性名或数组下标, 值)
将obj1对象的a属性赋值为字符串"b"并触发视图更新:
Vue.$set(this.obj1, a, "b")
如果在组件内,则应使用:
this.$set(this.obj1, a, "b")
Vue中关于数组与对象修改触发页面更新的机制与原理简析的更多相关文章
- vue数组对象修改触发视图更新
直接修改数组元素是无法触发视图更新的,如 this.array[0] = { name: 'meng', age: 22 } 修改array的length也无法触发视图更新,如 this.array. ...
- vue中改变数组或对象,页面没做出对应的渲染
原文链接 数组更新检测 变异方法 Vue 包含一组观察数组的变异方法,所以它们也将会触发视图更新.这些方法如下: push() pop() shift() unshift() splice() sor ...
- vue中watch数组或者对象
1.普通的watch data() { return { frontPoints: 0 } }, watch: { frontPoints(newValue, oldValue) { console. ...
- 【VUE】vue中遍历数组和对象
一.遍历对象 对象数据 cities:{ "A":[{ "id": 56, "spell": "aba", " ...
- 用VUE监听数组和对象的变化
看一下演示代码,先是增加数组和对象. <template> <div> <p>这是我定义的数组</p> <div>{{this.arr}}& ...
- Vue不能检测数组或对象变动问题的解决
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Vue实现对数组、对象的深拷贝、复制
当组件间传递对象时,由于此对象的引用类型指向的都是一个地址(除了基本类型跟null,对象之间的赋值,只是将地址指向同一个,而不是真正意义上的拷贝),如下 数组: ,,]; var b = a; b.p ...
- vue中改变数组的值视图无变化
今天开发的时候遇到一个多选取消点击状态的,渲染的时候先默认都选中,然后可以取消选中,自建了一个全为true的数组,点击时对应下标的arr[index]改为false,数据改变了状态没更新,突然想起来单 ...
- JS中深拷贝数组、对象、对象数组方法
我们在JS程序中需要进行频繁的变量赋值运算,对于字符串.布尔值等可直接使用赋值运算符 “=” 即可,但是对于数组.对象.对象数组的拷贝,我们需要理解更多的内容. 首先,我们需要了解JS的浅拷贝与深拷贝 ...
- JS中深拷贝数组、对象、对象数组方法(转载)
我们在JS程序中需要进行频繁的变量赋值运算,对于字符串.布尔值等可直接使用赋值运算符 “=” 即可,但是对于数组.对象.对象数组的拷贝,我们需要理解更多的内容. 首先,我们需要了解JS的浅拷贝与深拷贝 ...
随机推荐
- Redis一键安装脚本
#! /usr/bin/env bash # redis 6.0.3 源码安装 # 用法: bash -x install-redis-single.sh 6.0.3 version=$1 usage ...
- Prometheus自身的监控告警规则
1.先在 Prometheus 主程序目录下创建rules目录,然后在该目录下创建 prometheus-test.yml文件,内容如下: 内容很多,可以根据实际情况进行调整. 规则参考网址:http ...
- Docker/K8s 解决容器内时区不一致方案
转载自:https://cloud.tencent.com/developer/article/1433215 1.背景介绍 我们知道,使用 docker 容器启动服务后,如果使用默认 Centos ...
- 轻松绕过waf,内网技术,Cobalt Strike4.4远控木马绕waf流量监控
DNS隧道技术可以解决运控木马无法上线的问题,waf,防火墙对tcp,http,https等端口有流量检测,这个时候我们就可以使用隧道技术,让cs木马走DNS隧道,不仅可以检测不到而且也是一种反溯源的 ...
- GC plan_phase二叉树挂接的一个算法
楔子 在看GC垃圾回收plan_phase的时候,发现了一段特殊的代码,仔细研究下得知,获取当前数字bit位里面为1的个数. 通过这个bit位为1的个数(count),来确定挂接当前二叉树子节点的一个 ...
- 测试杂谈——一条SQL引发的思考(二)
在前段时间,曾写过一篇关于SQL问题的文章,测试杂谈--一条SQL引发的思考(一). 今天这篇,算是个问题记录吧,问题并不复杂,但对于测试同学而言,确实是个需要关注的点. 问题分析 最近在日常工作中, ...
- 【MySQL】01_运算符、函数
运算符 运算符是保留字或主要用于 SQL 语句的 WHERE 子句 中的字符,用于执行操作,例如:比较和算术运算. 这些运算符用于指定 SQL 语句中的条件,并用作语句中多个条件的连词. 常见运算符有 ...
- Win环境安装Protobuf 2.0 版本
转载请注明出处: 安装步骤 下载 protobuf-2.5.0.zip 与 protoc-2.5.0-win32.zip 下载链接 : https://github.com/protocolbuffe ...
- 通过jmeter连接人大金仓数据库
某项目用的人大金仓数据库,做性能测试,需要用jmeter来连接数据库处理一批数据.jmeter连接人大金仓,做个记录. 1. 概要 在"配置元件"中添加"JDBC Con ...
- springboot滚动分页展示列表(类似layui瀑布流效果)
背景: 公司项目要求获取用户关联的好友列表,要求分页查询,十条数据一页,滚动页面是点击加载更多,显示下一页列表. 示例图: 实现: 本项目采用的前端模板是freemaker,主要前端页面代码(没有 ...