Vue.js 中的 $watch使用方法

前端之家收集整理的这篇文章主要介绍了Vue.js 中的 $watch使用方法前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

这两天学习了Vue.js 中的 $watch这个地方知识点挺多的,而且很重要,所以,今天添加一点小笔记。

github 源码

Observer,Watcher,vm 可谓 Vue 中比较重要的部分,检测数据变动后视图更新的重要环节。下面我们来看看 如何实现一个简单的 $watch 功能,当然Vue 中使用了很多优化手段,在本文中暂不一一讨论。

例子:

// 键路径
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 实例。

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,{
enumerable: true,configurable: true,get: () => {
var value = getter ? getter.call(obj) : val
// 说明是 Watcher 初始化时获取的,就添加订阅
if (Dep.target) {
dep.depend()
if (childOb) {
childOb.dep.depend()
}
// if isArray do some....
}
return value
},set: (newVal) => {
var value = getter ? getter.call(obj) : val
if (value === newVal) {
return
}
if (setter) {
setter.call(obj,newVal)
} else {
val = newVal
}
childOb = observe(newVal)
dep.notify()
}
})
}

你可能会疑问 Dep.target 是个什么鬼?😳

答案是:Watcher, 我们接下来看

Dep

// 就是你!!~
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

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, 添加函数等等。

// 初始化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,fn)
}

总结

至此,我们已经实现了一个简单的 $watch 函数, Object.defineProperty() 函数可谓是举足轻重, 因此不支持函数的浏览器, Vue 均不支持

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程之家。

猜你在找的Vue相关文章