vue实现数据控制视图的原理解析


Posted in Javascript onJanuary 07, 2020

这篇主要讲的就是vue很重要的一块知识点,双向数据绑定是如何实现的。一开始看这一块的内容的时候比较迷茫,迷茫在以下几个点:

  1. 这块内容该从哪边入手
  2. 数据变化是如何驱动视图层更新的
  3. 做题深化知识点

从哪边着手去看响应式原理

我这边提供三个方向,从这三个方向,你都可以看到watcher的使用,然后watcher的使用过程中,会掺杂到observer以及dep,然后以点带面,对整体进行梳理

初始化的render流程去看

在lifecycle这个文件中的mountComponent这个方法里,创建了一个watcher。代码如下:

new Watcher(vm, updateComponent, noop, {
 before () {
  if (vm._isMounted && !vm._isDestroyed) {
  callHook(vm, 'beforeUpdate')
  }
 }
}, true /* isRenderWatcher */)

可以透过这个传参,梳理出整一个

  • 从watch的角度去看
  • 从computed的角度去看

数据变化是如何驱动视图层更新的

这个问题其实可以分两个方面去看:

如何知道数据变化了

如何知道某一块视图和数据有关,并更新他 如何知道数据变化了

答案:数据劫持

数据劫持的两种方式

Object.defineProperty
proxy

Vue3.0中的数据劫持是用proxy来实现的,目前阅读的源码中,都是以 Object.defineProperty 这种方式来实现的。

如何知道某一块视图和数据有关,并更新他

答案:依赖收集以及订阅更新

详细解读过程:用图告诉你响应式原理

这里仅用一个简单的例子和图,来明确一下整个流程

<div id="app">
 {{ message }}
 {{ message1 }}
 <input type="text" v-model="message">
 <div @click="changeMessage">改变message</div>  
</div>
var app = new Vue({
 el: '#app',
 data: {
  message: '1',
  message1: '2',
 },
 methods: {
  changeMessage() {
   this.message = '2'
  }
 },
 watch: {
  message: function(val) {
   this.message1 = val
  }
 }
})

依赖收集流程图

vue实现数据控制视图的原理解析

依赖收集的最终结果:

vue实现数据控制视图的原理解析

订阅更新流程图:

vue实现数据控制视图的原理解析

做题深化知识点

题目如下:

1、简述Vue的响应式原理

2、计算属性和watch的区别

3、Vue中给data中的对象属性添加一个新的属性时会发生什么,如何解决?

对于第一和第二在这里就不花篇幅去说明。

Vue中给data中的对象属性添加一个新的属性时会发生什么,如何解决?

我们在做业务的时候经常会遇到这样的情况,我举一个简单的例子:

<template>
 <div>
 <ul>
  <li v-for="value in obj" :key="value">
  {{value}}
  </li>
 </ul>
 <button @click="addObjB">添加obj.b</button>
 </div>
</template>
<script>
export default {
 data () {
 return {
  obj: {
  a: 'obj.a'
  }
 }
 },
 methods: {
 addObjB () {
  this.obj.b = 'obj.b'
  console.log(this.obj)
 }
 }
}
</script>
<style></style>

依赖收集流程:

vue实现数据控制视图的原理解析

从中我们可以发现,renderWatch是有收集 Dep(obj)Dep(Obj.a) 的,但是当我们改变Obj的时候,并没有触发视图的更新。因为我们在改变obj的值的时候,并没有去触发Dep(obj)。

产生问题的本质原因:

1、vue会在state.js文件的initData的方法中,将data属性中的每一个key都变成响应式属性。

2、视图在渲染过程中,会将renderWatcher收集到用到的值的dep中,方便依赖更新(不懂的在回过去看一下依赖收集流程)

3、当你额外添加一个属性的时候,该属性并不是响应式属性。

那如何去改变:

addObjB () {
 // this.obj.b = 'obj.b'
 this.$set(this.obj, 'b', 'obj.b')
 console.log(this.obj)
}

总结

这篇文章是年度总结的开篇,后续会继续总结初始化部分、render部分和patch部分。希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
Javascript面向对象编程(三) 非构造函数的继承
Aug 28 Javascript
js获取html参数及向swf传递参数应用介绍
Feb 18 Javascript
JS正则验证邮箱的格式详细介绍
Nov 19 Javascript
jQuery中fadeOut()方法用法实例
Dec 24 Javascript
jQuery中index()方法用法实例
Dec 27 Javascript
js通过iframe加载外部网页的实现代码
Apr 05 Javascript
js实现透明度渐变效果的方法
Apr 10 Javascript
JavaScript中对DOM节点的访问、创建、修改、删除
Nov 16 Javascript
jQuery事件的绑定、触发、及监听方法简单说明
May 10 Javascript
jquery实现转盘抽奖功能
Jan 06 Javascript
Angular2关于@angular/cli默认端口号配置的问题
Jul 15 Javascript
详解Vue.js在页面加载时执行某个方法
Nov 20 Javascript
微信小程序wx.navigateTo方法里的events参数使用详情及场景
Jan 07 #Javascript
详解微信小程序之提高应用速度小技巧
Jan 07 #Javascript
小程序跨页面交互的作用与方法详解
Jan 07 #Javascript
JavaScript实现联动菜单特效
Jan 07 #Javascript
JS实现电商商品展示放大镜特效
Jan 07 #Javascript
JS实现字体背景跑马灯
Jan 06 #Javascript
JS实现音乐钢琴特效
Jan 06 #Javascript
You might like
原生php实现excel文件读写的方法分析
2018/04/25 PHP
PHP array_reduce()函数的应用解析
2018/10/28 PHP
Prototype使用指南之dom.js
2007/01/10 Javascript
Javascript 继承实现例子
2009/08/12 Javascript
JavaScript栏目列表隐藏/显示简单实现
2013/04/03 Javascript
replace()方法查找字符使用示例
2013/10/28 Javascript
JavaScript极简入门教程(一):基础篇
2014/10/25 Javascript
EasyUI实现二级页面的内容勾选的方法
2015/03/01 Javascript
原生JavaScript编写俄罗斯方块
2015/03/30 Javascript
基于javascript实现图片预加载
2016/01/05 Javascript
javascript运动框架用法实例分析(实现放大与缩小效果)
2016/01/08 Javascript
jQuery封装的屏幕居中提示信息代码
2016/06/08 Javascript
js 连续赋值的简单实现
2016/06/13 Javascript
原生js开发的日历插件
2017/02/04 Javascript
JavaScript实现时间表动态效果
2017/07/15 Javascript
vue父组件中获取子组件中的数据(实例讲解)
2017/09/27 Javascript
简单的Vue SSR的示例代码
2018/01/12 Javascript
JS前后端实现身份证号验证代码解析
2020/07/23 Javascript
理解JavaScript中的对象
2020/08/25 Javascript
antd-日历组件,前后禁止选择,只能选中间一部分的实例
2020/10/29 Javascript
微信小程序将页面按钮悬浮固定在底部的实现代码
2020/10/29 Javascript
python实现封装得到virustotal扫描结果
2014/10/05 Python
go语言计算两个时间的时间差方法
2015/03/13 Python
python采集百度百科的方法
2015/06/05 Python
Python中random模块生成随机数详解
2016/03/10 Python
python画一个玫瑰和一个爱心
2020/08/18 Python
Python线程之定位与销毁的实现
2019/02/17 Python
python+selenium实现简历自动刷新的示例代码
2019/05/20 Python
python实现ip地址查询经纬度定位详解
2019/08/30 Python
PyCharm2020.3.2安装超详细教程
2021/02/08 Python
韩国三大免税店之一:THE GRAND 中文免税店
2016/07/21 全球购物
C语言编程题
2015/03/09 面试题
学生个人求职自荐信格式
2013/09/23 职场文书
学院领导推荐信
2013/10/30 职场文书
班级活动总结格式
2014/08/30 职场文书
JS Canvas接口和动画效果大全
2021/04/29 Javascript