开篇
最近在学习Vue的源码,看了网上一些大神的博客,看起来感觉还是蛮吃力的。自己记录一下学习的理解,希望能够达到简单易懂,不看源码也能理解的效果"color: #ff0000">Object.defineProperty
相信很多同学或多或少都了解Vue的响应式原理是通过Object.defineProperty实现的。被Object.defineProperty绑定过的对象,会变成「响应式」化。也就是改变这个对象的时候会触发get和set事件。进而触发一些视图更新。举个栗子"htmlcode">
function defineReactive (obj, key, val) { Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: () => { console.log('我被读了,我要不要做点什么好"数据被改变了,我要把新的值渲染到页面上去!"); } }) } let data = { text: 'hello world', }; // 对data上的text属性进行绑定 defineReactive(data, 'text', data.text); console.log(data.text); // 控制台输出 <我被读了,我要不要做点什么好"color: #ff0000">Observer 「响应式」
Vue中用Observer类来管理上述响应式化Object.defineProperty的过程。我们可以用如下代码来描述,将this.data也就是我们在Vue代码中定义的data属性全部进行「响应式」绑定。
class Observer { constructor() { // 响应式绑定数据通过方法 observe(this.data); } } export function observe (data) { const keys = Object.keys(data); for (let i = 0; i < keys.length; i++) { // 将data中我们定义的每个属性进行响应式绑定 defineReactive(obj, keys[i]); } }Dep 「依赖管理」
什么是依赖?
相信没有看过源码或者刚接触Dep这个词的同学都会比较懵。那Dep究竟是用来做什么的呢? 我们通过defineReactive方法将data中的数据进行响应式后,虽然可以监听到数据的变化了,那我们怎么处理通知视图就更新呢?
Dep就是帮我们收集【究竟要通知到哪里的】。比如下面的代码案例,我们发现,虽然data中有text和message属性,但是只有message被渲染到页面上,至于text无论怎么变化都影响不到视图的展示,因此我们仅仅对message进行收集即可,可以避免一些无用的工作。
那这个时候message的Dep就收集到了一个依赖,这个依赖就是用来管理data中message变化的。
<div> <p>{{message}}</p> </div>data: { text: 'hello world', message: 'hello vue', }当使用watch属性时,也就是开发者自定义的监听某个data中属性的变化。比如监听message的变化,message变化时我们就要通知到watch这个钩子,让它去执行回调函数。
这个时候message的Dep就收集到了两个依赖,第二个依赖就是用来管理watch中message变化的。
watch: { message: function (val, oldVal) { console.log('new: %s, old: %s', val, oldVal) }, }当开发者自定义computed计算属性时,如下messageT属性,是依赖message的变化的。因此message变化时我们也要通知到computed,让它去执行回调函数。 这个时候message的Dep就收集到了三个依赖,这个依赖就是用来管理computed中message变化的。
computed: { messageT() { return this.message + '!'; } }图示如下:一个属性可能有多个依赖,每个响应式数据都有一个Dep来管理它的依赖。
如何收集依赖
我们如何知道data中的某个属性被使用了,答案就是Object.defineProperty,因为读取某个属性就会触发get方法。可以将代码进行如下改造:
function defineReactive (obj, key, val) { let Dep; // 依赖 Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: () => { console.log('我被读了,我要不要做点什么好"数据被改变了,我要把新的值渲染到页面上去!"); } }) }什么是依赖
那所谓的依赖究竟是什么呢?上面的图中已经暴露了答案,就是Watcher。
Watcher 「中介」
Watcher就是类似中介的角色,比如message就有三个中介,当message变化,就通知这三个中介,他们就去执行各自需要做的变化。
Watcher能够控制自己属于哪个,是data中的属性的还是watch,或者是computed,Watcher自己有统一的更新入口,只要你通知它,就会执行对应的更新方法。
因此我们可以推测出,Watcher必须要有的2个方法。一个就是通知变化,另一个就是被收集起来到Dep中去。
class Watcher { addDep() { // 我这个Watcher要被塞到Dep里去了~~ }, update() { // Dep通知我更新呢~~ }, }总结
回顾一下,Vue响应式原理的核心就是Observer、Dep、Watcher。
Observer中进行响应式的绑定,在数据被读的时候,触发get方法,执行Dep来收集依赖,也就是收集Watcher。
在数据被改的时候,触发set方法,通过对应的所有依赖(Watcher),去执行更新。比如watch和computed就执行开发者自定义的回调方法。
本篇文章属于入门篇,能够先简单的理解Observer、Dep、Watcher三者的作用和关系。后面会逐渐详细和深入,循序渐进的理解和学习。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]