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 相关文章推荐
js中获取事件对象的方法小结
Mar 13 Javascript
深入解析contentWindow, contentDocument
Jul 04 Javascript
js之onload事件的一点使用心得
Aug 14 Javascript
超级简单的jquery操作表格方法
Dec 15 Javascript
javascript删除一个html元素节点的方法
Dec 20 Javascript
浅谈javascript实现八大排序
Apr 27 Javascript
两款JS脚本判断手机浏览器类型跳转WAP手机网站
Oct 16 Javascript
详解JavaScript中的Unescape()和String() 函数
Nov 09 Javascript
基于BootStrap Metronic开发框架经验小结【三】下拉列表Select2插件的使用
May 12 Javascript
JS区分Object与Aarry的六种方法总结
Feb 27 Javascript
vue使用element-ui的el-input监听不了回车事件的解决方法
Jan 12 Javascript
vue 中swiper的使用教程
May 22 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
有关phpmailer的详细介绍及使用方法
2013/01/28 PHP
关于zend studio 出现乱码问题的总结
2013/06/23 PHP
php判断ip黑名单程序代码实例
2014/02/24 PHP
php检查字符串中是否包含7位GSM字符的方法
2015/03/17 PHP
php+ajax无刷新分页实例详解
2015/12/07 PHP
PHP生成短网址方法汇总
2016/07/12 PHP
PHP ADODB生成下拉列表框功能示例
2018/05/29 PHP
Laravel5.3+框架定义API路径取消CSRF保护方法详解
2020/04/06 PHP
JavaScript聚焦于第一个字段的代码
2010/10/15 Javascript
jquery获取table中的某行全部td的内容方法
2013/03/08 Javascript
Javascript中查找不以XX字符结尾的单词示例代码
2013/10/15 Javascript
探讨jQuery的ajax使用场景(c#)
2013/12/03 Javascript
javascript字符串替换及字符串分割示例代码
2013/12/12 Javascript
使用JavaScript刷新网页的方法
2015/06/04 Javascript
javascript处理a标签超链接默认事件的方法
2015/06/29 Javascript
jQuery layui常用方法介绍
2016/07/25 Javascript
etmvc+jQuery EasyUI+combobox多值操作实现角色授权实例
2016/11/09 Javascript
Vue如何引入远程JS文件
2017/04/20 Javascript
Vue父组件调用子组件事件方法
2018/02/23 Javascript
基于Vue 服务端Cookies删除的问题
2018/09/21 Javascript
python 获取本机ip地址的两个方法
2013/02/25 Python
python实现可将字符转换成大写的tcp服务器实例
2015/04/29 Python
numpy 进行数组拼接,分别在行和列上合并的实例
2018/05/08 Python
Python OpenCV处理图像之滤镜和图像运算
2018/07/10 Python
使用python执行shell脚本 并动态传参 及subprocess的使用详解
2020/03/06 Python
Python爬虫如何破解JS加密的Cookie
2020/11/19 Python
美国网上眼镜供应商:LEOTONY(眼镜、RX太阳镜和太阳镜)
2017/10/31 全球购物
中专生毕业自我鉴定
2013/11/01 职场文书
会计与审计毕业生自荐信范文
2013/12/30 职场文书
二手房购房意向书范本
2014/04/01 职场文书
自我推荐信范文
2014/05/09 职场文书
火锅店的活动方案
2014/08/15 职场文书
学生党员批评与自我批评
2014/10/15 职场文书
2015年人事专员工作总结
2015/04/29 职场文书
python之np.argmax()及对axis=0或者1的理解
2021/06/02 Python
python缺失值填充方法示例代码
2022/12/24 Python