赞
踩
get:使用Dep来收集观察者
set:Dep派发通知给收集到的观察者
- class Observer {
- constructor (value: Object) {
- this.walk(value)
- }
- walk (obj: Object) {
- const keys = Object.keys(obj)
- for (let i = 0; i < keys.length; i++) { // 遍历对象的每个key
- defineReactive(obj, keys[i], obj[keys[i]])
- }
- }
- }
-
- const observe = (value: any) => {
- if (!isObject(value)) {
- return
- }
- return new Observer(value)
- }
-
- function defineReactive (
- obj: Object,
- key: string,
- val: any
- ) {
- const dep = new Dep() //给该属性创建依赖收集器
-
- observe(val) // 该属性可能是一个对象,用observe递归
- Object.defineProperty(obj, key, {
- enumerable: true,
- configurable: true,
- get: function reactiveGetter () {
- dep.depend() // 进行依赖收集,收集观察者
- return val
- },
- set: function reactiveSetter (newVal) {
- val = newVal
- observe(newVal) // 新的属性值可能是一个对象,用observe进行响应式处理,也就是重复以上的流程
- dep.notify() // 收集器派发通知给观察者
- }
- })
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- export default class Dep {
- constructor () {
- this.id = uid++
- this.subs = [] //收集器用来存放观察者的数组
- }
-
- addSub (sub: Watcher) {
- this.subs.push(sub)
- }
-
- depend () {
- if (window.target) {
- this.addSub(window.target) // 把观察者添加到subs数组上
- }
- }
-
- notify () {
- const subs = this.subs.slice()
- for (let i = 0, l = subs.length; i < l; i++) {
- subs[i].update()
- }
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- vm.$watch('user.name', function() {
- // doing sometings
- })
- class Watcher {
-
- constructor (
- vm: Component,
- expOrFn: string | Function,
- cb: Function,
- ) {
- this.vm = vm
- this.cb = cb
- this.getter = parsePath(expOrFn) // 解析user.name,生成访问name属性的函数
- this.value = this.get()
- }
-
- get () {
- window.target = this
- const vm = this.vm
- // getter是可以访问name属性的函数
- // 此时会触发name属性的get函数执行dep.depend收集观察者
- // 观察者在上面一步已经赋值到了window.target上了,dep.depend可以进行收集
- let value = this.getter.call(vm, vm)
- window.target = undefined // 收集完毕,清空window.target
- return value
- }
-
- // 当name属性被修改时,触发dep.notify。notify函数会执行观察者的update方法
- update () {
- const oldValue = this.value
- this.value = this.get()
- this.cb.call(this.vm, this.value, oldValue) // 执行$watch('user.name', cb)的回调函数
- }
-
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- const arrayProto = Array.prototype
- export const arrayMethods = Object.create(arrayProto)
-
- const methodsToPatch = [
- 'push',
- 'pop',
- 'shift',
- 'unshift',
- 'splice',
- 'sort',
- 'reverse'
- ]
-
- methodsToPatch.forEach(function (method) {
- const original = arrayProto[method]
- def(arrayMethods, method, function mutator (...args) {
- const result = original.apply(this, args)
- // todo。这里执行通知观察者的逻辑
- return result
- })
- })
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- class Observer {
- constructor (value: Object) {
- if(Array.isArray(value)) {
- value.__proto__ = arrayMethods // __proto__ 有兼容性问题 兼容性处理省略
- }else {
- this.walk(value)
- }
- }
- }
- class Observer {
- constructor (value: Object) {
- this.dep = new Dep() // 新增
- def(value, '__ob__', this) // 新增 在数组上添加__ob__属性指向当前的Observer实例
- if(Array.isArray(value)) {
- value.__proto__ = arrayMethods
- }else {
- this.walk(value)
- }
- }
- }
- methodsToPatch.forEach(function (method) {
- const original = arrayProto[method]
- def(arrayMethods, method, function mutator (...args) {
- const result = original.apply(this, args)
- this.__ob__.dep.notify() // 这里执行通知观察者的逻辑
- return result
- })
- })
- function defineReactive (
- obj: Object,
- key: string,
- val: any
- ) {
- const dep = new Dep()
-
- const childOb = observe(val)
- Object.defineProperty(obj, key, {
- enumerable: true,
- configurable: true,
- get: function reactiveGetter () {
- if(childOb) { // 新增
- childOb.dep.depend() // 新增
- }
- dep.depend()
- return val
- },
- set: function reactiveSetter (newVal) {
- val = newVal
- observe(newVal)
- dep.notify()
- }
- })
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- class Observer {
- constructor (value: Object) {
- if(Array.isArray(value)) {
- value.__proto__ = arrayMethods
- this.observerArray(value) // 新增
- }else {
- this.walk(value)
- }
- }
- }
-
- observeArray (items: Array<any>) {
- for (let i = 0, l = items.length; i < l; i++) {
- observe(items[i])
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。