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 相关文章推荐
Display SQL Server Version Information
Jun 21 Javascript
jQuery 入门讲解1
Apr 15 Javascript
解析js如何获取当前url中的参数值并复制给input
Jun 23 Javascript
JQuery表单验证插件EasyValidator用法分析
Nov 15 Javascript
老生常谈JavaScript中的this关键字
Oct 01 Javascript
浅谈JS读取DOM对象(标签)的自定义属性
Nov 21 Javascript
JavaScript学习笔记--常用的互动方法
Dec 07 Javascript
Angular 4依赖注入学习教程之ClassProvider的使用(三)
Jun 04 Javascript
js实现各浏览器全屏代码实例
Jul 03 Javascript
详解vue填坑之解决部分浏览器不支持pushState方法
Jul 12 Javascript
基于D3.js实现时钟效果
Jul 17 Javascript
功能完善的小程序日历组件的实现
Mar 31 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制作新闻系统的思路
2006/10/09 PHP
PHP setTime 设置当前时间的代码
2012/08/27 PHP
PHP中绘制图像的一些函数总结
2014/11/19 PHP
PHP图像处理之使用imagecolorallocate()函数设置颜色例子
2014/11/19 PHP
在PHP中输出JS语句以及乱码问题的解决方案
2019/02/13 PHP
Laravel实现ORM带条件搜索分页
2019/10/24 PHP
JQuery Dialog(JS 模态窗口,可拖拽的DIV)
2010/02/07 Javascript
js简易namespace管理器 实例代码
2013/06/21 Javascript
javascript实现的一个随机点名功能
2014/08/26 Javascript
JavaScript在Android的WebView中parseInt函数转换不正确问题解决方法
2015/04/25 Javascript
javascript实现网页端解压并查看zip文件
2015/12/15 Javascript
基于jQuery实现收缩展开功能
2016/03/18 Javascript
javascript鼠标滑过显示二级菜单特效
2020/11/18 Javascript
Webpack常见静态资源处理-模块加载器(Loaders)+ExtractTextPlugin插件
2017/06/29 Javascript
基于JavaScript实现带数据验证和复选框的表单提交
2017/08/23 Javascript
React教程之封装一个Portal可复用组件的方法
2018/01/02 Javascript
vue使用keep-alive保持滚动条位置的实现方法
2019/04/09 Javascript
vue+express+jwt持久化登录的方法
2019/06/14 Javascript
js实现页面多个日期时间倒计时效果
2019/06/20 Javascript
vue 路由缓存 路由嵌套 路由守卫 监听物理返回操作
2020/08/06 Javascript
Python urllib、urllib2、httplib抓取网页代码实例
2015/05/09 Python
在Python中操作列表之list.extend()方法的使用
2015/05/20 Python
python实现浪漫的烟花秀
2019/01/30 Python
Python I/O与进程的详细讲解
2019/03/08 Python
python编程进阶之类和对象用法实例分析
2020/02/21 Python
python shapely.geometry.polygon任意两个四边形的IOU计算实例
2020/04/12 Python
Python绘图实现台风路径可视化代码实例
2020/10/23 Python
python基于socket模拟实现ssh远程执行命令
2020/12/05 Python
CSS3实现的文本3D效果附图
2014/09/03 HTML / CSS
美国非常受欢迎的Spa品牌:Bliss必列斯
2018/04/10 全球购物
日本最大级玩偶手办购物:あみあみ Amiami
2018/04/23 全球购物
MyHeritage美国:家族史研究和DNA测试的领先服务
2019/05/27 全球购物
2014年管理人员工作总结
2014/12/01 职场文书
房产遗嘱范本
2015/08/06 职场文书
医务人员岗前培训心得体会
2016/01/08 职场文书
你有一份《诚信考试承诺书》待领取
2019/11/13 职场文书