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为空或不是对象问题的快速解决方法
Dec 11 Javascript
Node.js编码规范
Jul 14 Javascript
简单实现JS倒计时效果
Dec 23 Javascript
Angular企业级开发——MVC之控制器详解
Feb 20 Javascript
BootstrapValidator实现注册校验和登录错误提示效果
Mar 10 Javascript
解决Vue页面固定滚动位置的处理办法
Jul 13 Javascript
JS正则表达式完美实现身份证校验功能
Oct 18 Javascript
基于node下的http小爬虫的示例代码
Jan 11 Javascript
vue生成token并保存到本地存储中
Jul 17 Javascript
JS+HTML5实现获取手机验证码倒计时按钮
Aug 08 Javascript
layui实现图片虚拟路径上传,预览和删除的例子
Sep 25 Javascript
小程序实现左滑删除的效果的实例代码
Oct 19 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
Classes and Objects in PHP5-面向对象编程 [1]
2006/10/09 PHP
网页游戏开发入门教程三(简单程序应用)
2009/11/02 PHP
PHP FTP操作类代码( 上传、拷贝、移动、删除文件/创建目录)
2014/05/10 PHP
PHP函数in_array()使用详解
2014/08/20 PHP
文件上传之SWFUpload插件(代码)
2015/07/30 PHP
php注册系统和使用Xajax即时验证用户名是否被占用
2017/08/31 PHP
基于php流程控制语句和循环控制语句(讲解)
2017/10/23 PHP
Javascript处理DOM元素事件实现代码
2012/05/23 Javascript
学习javascript面向对象 理解javascript对象
2016/01/04 Javascript
javascript实现标签切换代码示例
2016/05/22 Javascript
jQuery无刷新上传之uploadify简单代码
2017/01/17 Javascript
vue-hook-form使用详解
2017/04/07 Javascript
深入理解nodejs中Express的中间件
2017/05/19 NodeJs
微信小程序封装http访问网络库实例代码
2017/05/24 Javascript
Angular2关于@angular/cli默认端口号配置的问题
2017/07/15 Javascript
node上的redis调用优化示例详解
2018/10/30 Javascript
VUE2.0 ElementUI2.0表格el-table自适应高度的实现方法
2018/11/28 Javascript
微信小程序页面传多个参数跳转页面的实现方法
2019/05/17 Javascript
Python实现根据指定端口探测服务器/模块部署的方法
2014/08/25 Python
Python中super的用法实例
2015/05/28 Python
Python 类与元类的深度挖掘 II【经验】
2016/05/06 Python
Python实现在tkinter中使用matplotlib绘制图形的方法示例
2018/01/18 Python
Python如何访问字符串中的值
2020/02/09 Python
python 比较字典value的最大值的几种方法
2020/04/17 Python
Python垃圾回收机制三种实现方法
2020/04/27 Python
python怎么删除缓存文件
2020/07/19 Python
pycharm中如何自定义设置通过“ctrl+滚轮”进行放大和缩小实现方法
2020/09/16 Python
解决python 执行shell命令无法获取返回值的问题
2020/12/05 Python
Html5新标签解释及用法
2012/02/17 HTML / CSS
英国网络托管和域名领导者:Web Hosting UK
2017/10/15 全球购物
酒店人事专员岗位职责
2013/12/19 职场文书
简历中个人自我评价分享
2014/03/15 职场文书
2016年青少年禁毒宣传教育活动总结(学校)
2016/04/05 职场文书
未来,这5大方向都很适合创业
2019/07/22 职场文书
html form表单基础入门案例讲解
2021/07/15 HTML / CSS
CSS实现单选折叠菜单功能
2021/11/01 HTML / CSS