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 相关文章推荐
ASP.NET jQuery 实例6 (实现CheckBoxList成员全选或全取消)
Jan 13 Javascript
javascript禁用Tab键脚本实例
Nov 22 Javascript
类似php的js数组的in_array函数自定义方法
Dec 27 Javascript
jQuery替换textarea中换行的方法
Jun 10 Javascript
Webwork 实现文件上传下载代码详解
Feb 02 Javascript
easyui window refresh 刷新两次的解决方法(推荐)
May 18 Javascript
jquery uploadify隐藏上传进度的实现方法
Feb 06 Javascript
js 公式编辑器 - 自定义匹配规则 - 带提示下拉框 - 动态获取光标像素坐标
Jan 04 Javascript
Array数组对象中的forEach、map、filter及reduce详析
Aug 02 Javascript
javascript设计模式 ? 策略模式原理与用法实例分析
Apr 21 Javascript
JavaScript async/await原理及实例解析
Dec 02 Javascript
vue3自定义dialog、modal组件的方法
Jan 04 Vue.js
微信小程序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
星际争霸, 教主第一视角, ZvT经典龙蛇演义
2020/03/02 星际争霸
PHP也可以?成Shell Script
2006/10/09 PHP
php自动给文章加关键词链接的函数代码
2012/11/29 PHP
解析PHP 使用curl提交json格式数据
2013/06/29 PHP
PHP调用Mailgun发送邮件的方法
2017/05/04 PHP
php设计模式之中介者模式分析【星际争霸游戏案例】
2020/03/23 PHP
JS中style属性
2006/10/11 Javascript
获取HTML DOM节点元素的方法的总结
2009/08/21 Javascript
Zero Clipboard js+swf实现的复制功能使用方法
2010/03/07 Javascript
JS事件Event元素(兼容IE,Firefox,Chorme)
2012/11/01 Javascript
JS事件在IE与FF中的区别详细解析
2013/11/20 Javascript
一个字符串反转函数可实现字符串倒序
2014/09/15 Javascript
js生成的验证码的实现与技术分析
2014/09/17 Javascript
jQuery使用height()获取高度需要注意的地方
2014/12/13 Javascript
JavaScript切换搜索引擎的导航网页搜索框实例代码
2017/06/11 Javascript
详解vue-resource promise兼容性问题
2017/06/20 Javascript
js编写简单的聊天室功能
2017/08/17 Javascript
vue better-scroll插件使用详解
2018/01/25 Javascript
Vue2 轮播图slide组件实例代码
2018/05/31 Javascript
利用Vue实现一个markdown编辑器实例代码
2019/05/19 Javascript
node脚手架搭建服务器实现token验证的方法
2021/01/20 Javascript
python del()函数用法
2013/03/24 Python
使用Python对IP进行转换的一些操作技巧小结
2015/11/09 Python
tf.truncated_normal与tf.random_normal的详细用法
2018/03/05 Python
python 正确保留多位小数的实例
2018/07/16 Python
PyQt5实现简易电子词典
2019/06/25 Python
在自动化中用python实现键盘操作的方法详解
2019/07/19 Python
基于python实现微信好友数据分析(简单)
2020/02/16 Python
Scrapy基于scrapy_redis实现分布式爬虫部署的示例
2020/09/29 Python
HTML5 Canvas如何实现纹理填充与描边(Fill And Stroke)
2013/07/15 HTML / CSS
博朗(Braun)俄罗斯官方商店:德国小家电品牌
2019/09/24 全球购物
五水共治一句话承诺
2014/05/30 职场文书
一篇文章了解正则表达式的替换技巧
2022/02/24 Javascript
MySql数据库触发器使用教程
2022/06/01 MySQL
Android基础入门之dataBinding的简单使用教程
2022/06/21 Java/Android
Nginx如何限制IP访问只允许特定域名访问
2022/07/23 Servers