Vue响应式原理之官方解释

当你把一个普通的JavaScript对象传给Vue实例的data选项,Vue将遍历此对象所有的属性,并使用Object.defineProperty把这些属性全部转为getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是为什么 Vue 不支持 IE8 以及更低版本浏览器。

这些getter/setter对用户来说是不可见的,但是在内部他们让vue追踪依赖,在属性被访问和修改时通知变化。每个组件实例都有相应的watcher实例对象,它会在组建渲染的过程中把属性记录为依赖,之后当依赖项的setter被调用时,会通知watcher重新计算,从而致使它关联的组件得以更新。


对象更改检测

在一个组件实例中,只有在data里初始化的数据才是响应的,Vue不能检测到对象属性的添加或删除,没有在data里声明的属性不是响应的。

Vue不允许在已经创建的实例上动态添加根级响应式属性,但是可以使用$set方法将相应属性添加到嵌套的对象上。

例子一:属性a是已经声明了的,是响应的;属性b没有提前声明,因此改变了属性b的值的时候,如果直接赋值 this.form.b = 'desc'  , 虽然打印出来的值是改变了的,但是视图并没有更新。需要用Vue.set(object, key, value) 【或 this.$set(object,key,value)】 方法将响应属性添加到嵌套的对象上。注意:object 必须是在data中已经声明的对象。

......
<section>
<p>动态添加嵌套属性1:</p>
<p>a的值{{form.a}}</p>
<p>b的值{{form.b}}</p>
<el-button @click="changeA">改变A</el-button>
<el-button @click="changeB">改变B</el-button>
</section>
.......
export default {
name: "layout",
data(){
return {
form:{
a:''//初始化
}
}
},
methods:{
changeA(){
this.form.a = 1
},
changeB(){
      //this.form.b = 'desc' //无效
this.$set(this.form,'b','desc')//动态添加
      //或者 Vue.set(vm.form,'b','desc')
}
}
}
</script>

例子二:Vue.set(object,key,value)方法一次只能添加一个属性,如果需要向嵌套对象上添加多个属性,可以用Object.assign方法。object.assign方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象,并返回目标对象。

vm.object = Object.assign( { } , vm.object , {a:' 1 ', b:' 2 ' })  注:object必须是已经声明的对象

......
<section>
<p>object.assign方法</p>
<p>{{form3.f1}}</p>
<p>{{form3.f2}}</p>
<el-button @click="changeForm3">添加多个属性</el-button>
</section>
...... export default {
name: "layout",
data(){
return {
form3:{}
}
},
methods:{
changeForm3(){
this.form3 = Object.assign({},this.form3,{f1:'f1',f2:'f2'})
}
}
}

数组渲染问题

通过改动两种方式改动数组时,Vue检测不到变动:1.利用索引直接设置一个项;2.修改数组长度。

例子三:利用索引直接设置一个项,不能直接触发状态更新。

<p v-for="(item,index) in trees" @click="changeMe(index)">这个是{{item}}</p>

export default {
name: "layout",
data(){
return {
trees:['a','b','c']
}
},
methods:{
changeMe(idx){
//this.trees[idx] = 'x'//无响应
this.$set(this.trees,idx,'x')//有响应
      //this.trees.splice(idx,1,'x')//有响应       }
      }
}

例子四:改变数组长度

      <p v-for="(item,index) in trees">这个是{{item}}</p>
<el-button @click="changeLength">改变长度</el-button> export default {
name: "layout",
data(){
return {
trees:['a','b','c']
}
},
methods:{
changeLength(){
//this.trees.length = 2//无响应
this.trees.splice(2)//有响应
}
}
}

vue数据更改视图不更新问题----深入响应式原理的更多相关文章

  1. Vue.js 源码分析(四) 基础篇 响应式原理 data属性

    官网对data属性的介绍如下: 意思就是:data保存着Vue实例里用到的数据,Vue会修改data里的每个属性的访问控制器属性,当访问每个属性时会访问对应的get方法,修改属性时会执行对应的set方 ...

  2. Vue.js 技术揭秘(学习) 深入响应式原理 nextTick外传

    microTask  mutationObserve. promise.then macroTask setImmediate. messageChannnel.setTimeout.postMess ...

  3. Vue的响应式原理

    Vue的响应式原理 一.响应式的底层实现 1.Vue与MVVM Vue是一个 MVVM框架,其各层的对应关系如下 View层:在Vue中是绑定dom对象的HTML ViewModel层:在Vue中是实 ...

  4. Vue 数据响应式原理

    Vue 数据响应式原理 Vue.js 的核心包括一套“响应式系统”.“响应式”,是指当数据改变后,Vue 会通知到使用该数据的代码.例如,视图渲染中使用了数据,数据改变后,视图也会自动更新. 举个简单 ...

  5. 一探 Vue 数据响应式原理

    一探 Vue 数据响应式原理 本文写于 2020 年 8 月 5 日 相信在很多新人第一次使用 Vue 这种框架的时候,就会被其修改数据便自动更新视图的操作所震撼. Vue 的文档中也这么写道: Vu ...

  6. vue 数据劫持 响应式原理 Observer Dep Watcher

    1.vue响应式原理流程图概览 2.具体流程 (1)vue示例初始化(源码位于instance/index.js) import { initMixin } from './init' import ...

  7. vue深入响应式原理

    vue深入响应式原理 深入响应式原理 — Vue.jshttps://cn.vuejs.org/v2/guide/reactivity.html 注意:这里说的响应式不是bootsharp那种前端UI ...

  8. Vue.js学习 Item12 – 内部响应式原理探究

    深入响应式原理 大部分的基础内容我们已经讲到了,现在讲点底层内容.Vue.js 最显著的一个功能是响应系统 —— 模型只是普通对象,修改它则更新视图.这让状态管理非常简单且直观,不过理解它的原理也很重 ...

  9. Vue.js响应式原理

      写在前面 因为对Vue.js很感兴趣,而且平时工作的技术栈也是Vue.js,这几个月花了些时间研究学习了一下Vue.js源码,并做了总结与输出. 文章的原地址:answershuto/learnV ...

随机推荐

  1. Bag of Tricks for Image Classification with Convolutional Neural Networks

    url: https://arxiv.org/abs/1812.01187 year: 2018 文中介绍了训练网络的一些 tricks, 通过组合训练过程的trick,来提高模型性能和泛化能力,以及 ...

  2. 用go-module作为包管理器搭建go的web服务器

    本篇博客主要介绍了如何从零开始,使用Go Module作为依赖管理,基于Gin来一步一步搭建Go的Web服务器.并使用Endless来使服务器平滑重启,使用Swagger来自动生成Api文档. 源码在 ...

  3. Web前端——Html常用标签及属性

    html 常用的标题等标签就不记录了,只记录一下比较少见的标签以及属性 表格 table td 单元格 tr 表的行 th 表头 td或th可以下面的两个属性达到跨行或跨列 表格跨行 rowspan ...

  4. wpf 当DataGrid列模版是ComboBox时,显示信息

    ​ 实际工作中,有时DataGrid控件某一列显示数据是从Enum集合里面选择出来的,那这时候设置列模版为ComboBox就能满足需求.而关于显示的实际内容,直接是Enum的string()返回值可能 ...

  5. Java技巧——比较两个日期相差的天数

    Java技巧——比较两个日期相差的天数 摘要:本文主要记录了在Java里面如何判断两个日期相差的天数. 判断两个Date类型的日期之间的天数 通过计算毫秒数判断: public static void ...

  6. MySQL学习——存储引擎

    MySQL学习——存储引擎 摘要:本文主要学习了MySQL数据库的存储引擎. 什么是存储引擎 数据库存储引擎是数据库底层软件组件,数据库管理系统使用数据引擎进行创建.查询.更新和删除数据操作.不同的存 ...

  7. js个人笔记简记

    正则表达式 创建正则表达式的两种方法:   Var reg = new RegExp(‘’) Var reg = / a/ 后面三个参数g:全局匹配 i:不区分大小写 m:多行匹配 开头结尾有用 常见 ...

  8. 程序员的自我修养系列(一):优雅的代码管理工具之GitHub

    1.导言 代码管理是程序员经常遇到一个问题,很多童鞋将代码保存到本地硬盘,此种方法管理混乱,也存在代码丢失的风险,且版本无法控制,因此养成良好的代码管理习惯是程序员的必修课.在众多代码管理工具中笔者在 ...

  9. java中字符串String、StringBuilder、StringBuffer的常用方法

    String的常用方法: public static void main(String[] args) { String str = "Hello world!"; // 获取字符 ...

  10. docker镜像管理(二)

    docker镜像 docker镜像含有启动容器所需要的文件系统和内容,因此,其用于创建并启动docker容器 docker镜像采用分层构建机制,最底层为bootfs,其之为rootfs bootfs: ...