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 相关文章推荐
可拖动窗口,附带鼠标控制渐变透明,开启关闭功能
Jun 26 Javascript
载入进度条 效果
Jul 08 Javascript
点击广告后才能获得下载地址
Oct 26 Javascript
JavaScript中使用Substring删除字符串最后一个字符
Nov 03 Javascript
jQuery操作基本控件方法实例分析
Dec 31 Javascript
JavaScript制作弹出层效果
Dec 02 Javascript
jquery拼接ajax 的json和字符串拼接的方法
Mar 11 Javascript
vue2利用Bus.js如何实现非父子组件通信详解
Aug 25 Javascript
vue脚手架中配置Sass的方法
Jan 04 Javascript
JavaScript面向对象的程序设计(犯迷糊的小羊)
May 27 Javascript
uni-app如何实现增量更新功能
Jan 03 Javascript
JavaScript Blob对象原理及用法详解
Oct 14 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
dedecms后台验证码总提示错误的解决方法
2007/03/21 PHP
用PHP伪造referer突破网盘禁止外连的代码
2008/06/15 PHP
php flv视频时间获取函数
2010/06/29 PHP
php生成随机颜色的方法
2014/11/13 PHP
PHP Header失效的原因分析及解决方法
2016/11/16 PHP
PHP7 安装event扩展的实现方法
2019/10/08 PHP
深入认识javascript中的eval函数
2009/11/02 Javascript
js汉字排序问题 支持中英文混排,兼容各浏览器,包括CHROME
2011/12/20 Javascript
Jquery插件写法笔记整理
2012/09/06 Javascript
Jsonp post 跨域方案
2015/07/06 Javascript
jQuery表单验证插件解析(推荐)
2016/07/21 Javascript
webix+springmvc session超时跳转登录页面
2016/10/30 Javascript
BootStrap树状图显示功能
2016/11/24 Javascript
jQuery弹出div层过2秒自动消失
2016/11/29 Javascript
Canvas 绘制粒子动画背景
2017/02/15 Javascript
浅析JavaScript中var that=this
2017/02/17 Javascript
使用OPENLAYERS3实现点选的方法
2020/09/24 Javascript
vue 粒子特效的示例代码
2017/09/19 Javascript
微信小程序实现image组件图片自适应宽度比例显示的方法
2018/01/16 Javascript
又拍云 Node.js 实现文件上传、删除功能
2018/10/28 Javascript
vue项目首屏加载时间优化实战
2019/04/23 Javascript
vue-router 前端路由之路由传值的方式详解
2019/04/30 Javascript
node.js中npm包管理工具用法分析
2020/02/14 Javascript
JavaScript实现刮刮乐效果
2020/11/01 Javascript
[54:54]Newbee vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
Python 2.7.x 和 3.x 版本的重要区别小结
2014/11/28 Python
python 字符串追加实例
2019/07/20 Python
python列表生成器迭代器实例解析
2019/12/19 Python
橄榄树药房:OLIVEDA
2019/09/01 全球购物
.net面试题
2015/12/22 面试题
奶茶店创业计划书范文
2014/01/17 职场文书
幼儿园秋游感想
2014/03/12 职场文书
中层领导干部群众路线对照检查材料思想汇报
2014/10/02 职场文书
JavaScript实例 ODO List分析
2022/01/22 Javascript
利用JuiceFS使MySQL 备份验证性能提升 10 倍
2022/03/17 MySQL
Golang Elasticsearches 批量修改查询及发送MQ
2022/04/19 Golang