这两天学习了Vue.js 中的 $watch这个地方知识点挺多的,而且很重要,所以,今天添加一点小笔记。
github 源码
Observer, Watcher, vm 可谓 Vue 中比较重要的部分,检测数据变动后视图更新的重要环节。下面我们来看看 如何实现一个简单的 $watch 功能,当然Vue 中使用了很多优化手段,在本文中暂不一一讨论。
例子:
// 创建 vm let vm = new Vue({ data: 'a' }) // 键路径 vm.$watch('a.b.c', function () { // 做点什么 })
先阐明在这个 demo 以及Vue 中,它们的关系:
vm 调用 $watch 后,首先调用 observe 函数 创建 Observer 实例观察数据,Observer 又创建 Dep , Dep 用来维护订阅者。然后创建 Watcher 实例提供 update 函数。一旦数据变动,就层层执行回调函数。
Observer和observe
递归调用 observe 函数创建 Observer。在创建 Observer 的过程中,使用 Object.defineProperty() 函数为其添加 get set 函数, 并创建 Dep 实例。
export function observe (val) { if (!val || typeof val !== 'object') { return } return new Observer(val) }
function defineReactive (obj, key, val) { var dep = new Dep() var property = Object.getOwnPropertyDescriptor(obj, key) // 是否允许修改 if (property && property.configurable === false) { return } // 获取定义好的 get set 函数 var getter = property && property.get var setter = property && property.set var childOb = observe(val) Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: () => { var value = getter "htmlcode">export default function Dep () { this.subs = [] } // 就是你!!~ Dep.target = null // 添加订阅者 Dep.prototype.addSub = function (sub) { this.subs.push(sub) } // 添加依赖 Dep.prototype.depend = function () { Dep.target.addDep(this) } // 通知订阅者:要更新啦~ Dep.prototype.notify = function () { this.subs.forEach(sub => sub.update()) }Watcher
为了给每个数据添加订阅者,我们想到的办法是在数据的 get 函数中, 但是 get 函数会调用很多次呀~。。。 肿么办?那就给 Dep 添加个参数 target
export default function Watcher (vm, expOrFn, cb) { this.cb = cb this.vm = vm this.expOrFn = expOrFn this.value = this.get() } Watcher.prototype.get = function () { Dep.target = this const value = this.vm._data[this.expOrFn] // 此时 target 有值,此时执行到了上面的 defineReactive 函数中 get 函数。就添加订阅者 Dep.target = null // 为了不重复添加 就设置为 null return value }Vue Instance
在 Vue Instance 做得最多的事情就是初始化 State, 添加函数等等。
// Vue 实例 export default function Vue(options) { this.$options = options this._initState() } // 初始化State Vue.prototype._initState = function () { let data = this._data = this.$options.data Object.keys(data).forEach(key => this._proxy(key)) observe(data, this) } // $watch 函数, Vue.prototype.$watch = function (expOrFn, fn, options) { new Watcher(this, expOrFn, fn) }总结
至此,我们已经实现了一个简单的 $watch 函数, Object.defineProperty() 函数可谓是举足轻重, 因此不支持该函数的浏览器, Vue 均不支持。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
华山资源网 Design By www.eoogi.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
华山资源网 Design By www.eoogi.com
暂无评论...
更新日志
2024年11月18日
2024年11月18日
- 【雨果唱片】中国管弦乐《鹿回头》WAV
- APM亚流新世代《一起冒险》[FLAC/分轨][106.77MB]
- 崔健《飞狗》律冻文化[WAV+CUE][1.1G]
- 罗志祥《舞状元 (Explicit)》[320K/MP3][66.77MB]
- 尤雅.1997-幽雅精粹2CD【南方】【WAV+CUE】
- 张惠妹.2007-STAR(引进版)【EMI百代】【WAV+CUE】
- 群星.2008-LOVE情歌集VOL.8【正东】【WAV+CUE】
- 罗志祥《舞状元 (Explicit)》[FLAC/分轨][360.76MB]
- Tank《我不伟大,至少我能改变我。》[320K/MP3][160.41MB]
- Tank《我不伟大,至少我能改变我。》[FLAC/分轨][236.89MB]
- CD圣经推荐-夏韶声《谙2》SACD-ISO
- 钟镇涛-《百分百钟镇涛》首批限量版SACD-ISO
- 群星《继续微笑致敬许冠杰》[低速原抓WAV+CUE]
- 潘秀琼.2003-国语难忘金曲珍藏集【皇星全音】【WAV+CUE】
- 林东松.1997-2039玫瑰事件【宝丽金】【WAV+CUE】