Vue的响应式规则
对象属性的响应规则
<body>
<div id="root">
{{msg}}
</div>
</body>
<script>
var app = new Vue({
el:"#root",
data:{
msg:{
a:123,
b:{
k:999
}
}
}
})
console.log(app)
</script>
运行结果:

可见,vue初始化时创建的getter/setter是递归创建的,不管这个值是否是对象,都会为这个属性创建 getter和setter 方法。有了这些getter和setter方法,直接执行:
app.msg.b = 999;
app.msg.a = 9990;
app.msg['a'] = 999;
app.msg = {xx:33};
以上都是响应式的。
或者直接把msg替换了也是响应式的,因为msg也有对应的getter和setter(文档中这一句:this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 }) 也只是变相地使用了这个规则而已),以下代码1s后在界面上显示123:
<body>
<div id="root">
{{msg.a}}
</div>
</body>
<script>
new Vue({
el:"#root",
data:{
msg:""
},
mounted:function(){
setTimeout(()=>{
this.msg = {a:123}
},1000)
},
});
</script>
对于规则:Vue 不允许在已经创建的实例上动态添加新的根级响应式属性(root-level reactive property)。
以上面的代码为例,不允许动态创建与msg同级别的属性。但可以通过set往msg中动态添加属性:
Vue.set(app.msg,"c",998)
Vue.set(app.msg,"d",{
x:458
})
通过set添加的属性,都会被设置setter和getter,如果值是对象,则对象中的属性也会被设置getter和setter:

数组的响应规则
注意:数组对象是个例外,vue会为数组对象本身设置getter和setter,但不会为数组对象内的属性0,1,以及length属性设置getter和setter,假如元素为对象,则会为这个对象内的属性设置getter和setter:

以上可以发现,要想达到响应效果,不能纯粹以一个对象的角度来看待数组,需要一些vue内置的数组函数来帮忙
https://vuefe.cn/v2/guide/list.html#变化数组方法-Mutation-Methods
使用Object.assign也能触发set方法,也就是说也是响应式的:
let x = {
set y(a){
console.log("设置 y 的值等于" + a)
}
};
x.y = 123; // 设置 y 的值等于123
Object.assign(x,{
y:999
}) // 设置 y 的值等于999
执行arr[0] = newObj; 这句代码没有响应式效果。但是利用以上Object.assign的效果,想要更新数组元素可以这么写:
Object.assign(arr[0], newObj)。 这样能实现一次更新数组元素中的多个属性,而且是响应式的。
踩坑记录
组件嵌套三层,分别记为A->B->C,C是最里层。
A异步请求数据,请求完成后,更新当前的data中的数据。意味着data中的数据会存在一个由初始值变为实际值的过程,会进行一次变化。
A中的一次变化,也会导致B和C中分别出现一次变化。
A主要就是请求数据,以及组装其他组件,如B。
而B中使用了C组件,B组件中对传入的数据进行格式化(通过计算属性),后把计算属性传递给C组件
C组件主要用于展示数据,以及维护自己内部的交互逻辑。
以上做法首先遇到问题:
1.C中需要修改传入的数据,如一个数组中的元素对象,发现修改后,C中界面没有根据修改后的数据而刷新
解决:C中emit一个事件,让B在处理事件中,直接对计算属性进行修改。效果:能自动反映到C中。但传递事件太麻烦,代码繁琐。
2.在C中创建data数据,其中直接返回B传入的计算属性。因为data属性在组件创建时只更新一次,即获取到的实际上是A传入的初始化数据,而后续再传入实际数据就接受不到了
解决:在C中多加一个watch,监视计算属性,当计算属性发生变化时,将新的值赋值给data数据,以达到C中本地的data数据实时依据外部数据而更新,如
props:["lArr","rArr"],
data:function(){
return {
lArrC:[],
rArrC:[]
}
},
watch:{
lArr:function(nV){
this.lArrC = nV;
},
rArr:function(nV){
this.rArrC = nV;
}
},
结论:组件中的数据来源有三:data中初始化的、计算属性和父组件通过props传入的,其中只有前两种存在响应式(仅针对当前组件)
另外一个记录:
有A、B两个组件,A异步数据,B负责展示数据(根据A传入的数据,如一个userid,进行一次异步请求,展示请求得到的详细数据)
因为A是异步请求的数据,所以最开始传给B的数据是默认数据,是无效的,那B该什么时候根据传入的数据来开始自己的异步请求呢?
第一种尝试:在B中watch,监视userid,发现userid变化了,而且userid不为空时,就开始请求数据。结果:就算A组件中的userid发生了变化,B中对userid进行watch,发现没有生效。
第二种尝试:在A中控制,当还没请求到数据时,通过v-if控制B组件不显示,当A中的异步数据到了后,再将B展示出来,这时B中的create方法会重新执行,在里面获取到传入的数据就必定是有效的了,即created中请求异步数据即可
Vue的响应式规则的更多相关文章
- vue.js响应式原理解析与实现
vue.js响应式原理解析与实现 从很久之前就已经接触过了angularjs了,当时就已经了解到,angularjs是通过脏检查来实现数据监测以及页面更新渲染.之后,再接触了vue.js,当时也一度很 ...
- vue深入响应式原理
vue深入响应式原理 深入响应式原理 — Vue.jshttps://cn.vuejs.org/v2/guide/reactivity.html 注意:这里说的响应式不是bootsharp那种前端UI ...
- Vue 数据响应式原理
Vue 数据响应式原理 Vue.js 的核心包括一套“响应式系统”.“响应式”,是指当数据改变后,Vue 会通知到使用该数据的代码.例如,视图渲染中使用了数据,数据改变后,视图也会自动更新. 举个简单 ...
- 深入解析vue.js响应式原理与实现
vue.js响应式原理解析与实现.angularjs是通过脏检查来实现数据监测以及页面更新渲染.之后,再接触了vue.js,当时也一度很好奇vue.js是如何监测数据更新并且重新渲染页面.vue.js ...
- Vue的响应式原理
Vue的响应式原理 一.响应式的底层实现 1.Vue与MVVM Vue是一个 MVVM框架,其各层的对应关系如下 View层:在Vue中是绑定dom对象的HTML ViewModel层:在Vue中是实 ...
- vue中响应式props办法
title: vue中响应式props办法 toc: false date: 2018-12-25 21:22:49 categories: Web tags: Vue 更新props数据时,使用th ...
- vue系列---响应式原理实现及Observer源码解析(一)
_ 阅读目录 一. 什么是响应式? 二:如何侦测数据的变化? 2.1 Object.defineProperty() 侦测对象属性值变化 2.2 如何侦测数组的索引值的变化 2.3 如何监听数组内容的 ...
- Vue的响应式系统
Vue的响应式系统 我们第一次使用Vue的时候,会感觉有些神奇,举个例子: <div id="app"> <div>价格:¥{{price}}</di ...
- Vue可响应式数组方法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
随机推荐
- CF1110F Nearest Leaf
传送门 这是我第二次看见这个题目了,第一次看见是另一场比赛的A题,想了一个小时不会写就弃了 从来没想过这个题能这么玩 线段树上记录根到叶子节点的距离 初始线段树上先记下根节点1到各叶子节点的距离 先离 ...
- JVM加载类的原理机制
在Java中,类装载器把一个类装入Java虚拟机中,要经过三个步骤来完成:装载.链接和初始化,其中链接又可以分成校验.准备.解析装载:查找和导入类或接口的二进制数据: 链接:执行下面的校验.准备和解析 ...
- Java | 基础归纳 | JPA
https://www.javacodegeeks.com/2015/04/jpa%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B.html JPA 全称====>Jav ...
- java操作rabbitmq实现简单的消息发送(socket编程的升级)
准备: 1.下载rabbitmq并搭建环境(和python那篇一样:http://www.cnblogs.com/g177w/p/8176797.html) 2.下载支持的jar包(http://re ...
- [題解]luogu_P1613跑路(最短路/倍增)
首先要知道不能跑最短路,因為只有整2^k才能一秒到達,和倍增有關 所以我們想知道任意兩點間能否存在一條2^k長度的路徑,數據很小,可以考慮floyd 把倍增和floyd結合起來考慮發現如果i到k,k到 ...
- (洛谷 P1429 平面最近点对(加强版) || 洛谷 P1257 || Quoit Design HDU - 1007 ) && Raid POJ - 3714
这个讲的好: https://phoenixzhao.github.io/%E6%B1%82%E6%9C%80%E8%BF%91%E5%AF%B9%E7%9A%84%E4%B8%89%E7%A7%8D ...
- Exception in thread "main" java.lang.SecurityException: class "javax.servlet.FilterRegistration"'s signer information does not match signer information of other classes in the same package解决办法(图文详解)
不多说,直接上干货! 问题详情 SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation. SLF ...
- 牛客网Java刷题知识点之什么是HTTP协议、什么是HTTP隧道、HTTP响应的结构是怎么样的、HTTP报头包含哪些、HTTP中GET与POST方法有什么区别
不多说,直接上干货! https://www.nowcoder.com/ta/review-java/review?tpId=31&tqId=21169&query=&asc= ...
- Java动态解析域名
Java动态解析域名 Java提供InetAddress类,可以对域名-IP进行正向.逆向解析. InetAddress解析的时候一般是调用系统自带的DNS程序. linux 默认的DNS方式是读取/ ...
- HashMap之put方法流程解读
说明:本文中所谈论的HashMap基于JDK 1.8版本源码进行分析和说明. HashMap的put方法算是HashMap中比较核心的功能了,复杂程度高但是算法巧妙,同时在上一版本的基础之上优化了存储 ...