1.在执行get()前进行依赖收集 更新后 清除依赖
get() {
// 渲染watch Dep.target = watcher;
// msg 变化了 需要重新执行watch
pushTarget(this)
// 让当前传入的函数执行
this.getter();
popTarget()
}
2.添加dep.js 文件
let id = 0;
class Dep {
constructor() {
this.id = id++;
this.subs = []
}
// 订阅
addSub(watcher) {
this.subs.push(watcher)
}
// 发布
notify() {
this.subs.forEach(watcher => {
watcher.update()
})
}
depend() {
if (Dep.target) {
Dep.target.addDep(this)
}
}
}
// 保存当前的watcher
let stack = [];
export function pushTarget(watcher) {
Dep.target = watcher;
stack.push(watcher)
}
// 取出
当前的watcher
export function popTarget(watcher) { stack.pop(watcher) Dep.target = stack[stack.length - 1] } // 收集依赖 export default Dep;
添加发布 订阅
addSub(watcher) {
this.subs.push(watcher)
}
将 所有 的 watcher 添加到数组 中
notify() {
this.subs.forEach(watcher => {
watcher.update()
})
}
将数组中的所有 watcher 拿出 执行 update 方法
3. 在对象进行 Object.defineProperty 执行 get 方法的时候 进行判断
if (Dep.target) {
dep.depend();
debugger;
// 数组的依赖收集 对象不存在
if (childObj) {
console.log(11111000)
// 数组也收集依赖
childObj.dep.depend()
dependArray(value);
}
}
先引入 dep
let dep = new Dep()
如果 Dep.target 有值 调用 dep.depend(); 方法 也就是
depend() {
if (Dep.target) {
Dep.target.addDep(this)
}
}
渲染watcher 记忆住 Dep
执行 set 方法的时候 发布通知
set(newValue) {
if (newValue !== value) return;
observe(newValue)
value = newValue
dep.notify()
}
通知调用 dep的 notify 方法
// 发布
notify() {
this.subs.forEach(watcher => {
watcher.update()
})
}
在这个方法中调用了 update 方法 update 又调用了 get 方法
update() {
this.get()
}
get 方法进行以下操作 又调用了 getter 方法
get() {
// 渲染watch Dep.target = watcher;
// msg 变化了 需要重新执行watch
pushTarget(this)
// 让当前传入的函数执行
this.getter();
popTarget()
}
getter 方法调用了 Vue.prototype.$update 方法进行 编译更新数据
完整 的 dep.js 和watch.js文件
let id = 0;
class Dep {
constructor() {
this.id = id++;
this.subs = []
}
// 订阅
addSub(watcher) {
this.subs.push(watcher)
}
// 发布
notify() {
this.subs.forEach(watcher => {
watcher.update()
})
}
depend() {
if (Dep.target) {
Dep.target.addDep(this)
}
}
}
// 保存当前的watcher
let stack = [];
export function pushTarget(watcher) {
Dep.target = watcher;
stack.push(watcher)
}
export function popTarget(watcher) {
stack.pop(watcher)
Dep.target = stack[stack.length - 1]
}
// 收集依赖
export default Dep;
let id = 0;
import { pushTarget, popTarget } from './dep'
class Watcher {
// watch 有唯一标识
constructor(vm, exprOrfn, cb = () => { }, opts = {}) {
// exprOrfn 表达式 cb 回调
this.vm = vm;
this.exprOrfn = exprOrfn;
if (typeof exprOrfn == 'function') {
// getter 就是 Watcher 传入的第2个函数
this.getter = exprOrfn;
}
this.cb = cb;
this.opts = opts;
this.id = id++;
this.deps = [];
this.depsId = new Set();
this.get()
}
get() {
// 渲染watch Dep.target = watcher;
// msg 变化了 需要重新执行watch
pushTarget(this)
// 让当前传入的函数执行
this.getter();
popTarget()
}
update() {
this.get()
}
addDep(dep) {
let id = dep.id;
if (!this.depsId.has(id)) {
this.depsId.add(id)
this.deps.push(dep)
dep.addSub(this)
}
}
}
export default Watcher;
observe.js 文件
// 定义响应式的数据变化
import { observe } from './index'
import { observerArray } from './array'
import { arrayMethod } from './array'
import Dep from './dep';
export function dependArray(value) {
console.log(2222)
for (let i = 0; i < value.length; i++) {
let current = value[i];
current.__ob__ && current.__ob__.dep.depend()
if (Array.isArray(current)) {
dependArray(current)
}
}
}
export function defineReactive(data, key, value) {
let childObj = observe(value);
let dep = new Dep()
Object.defineProperty(data, key, {
get() {
// 有值
if (Dep.target) {
dep.depend();
debugger;
// 数组的依赖收集 对象不存在
if (childObj) {
console.log(11111000)
// 数组也收集依赖
childObj.dep.depend()
dependArray(value);
}
}
return value;
},
set(newValue) {
if (newValue !== value) return;
observe(newValue)
value = newValue
dep.notify()
}
})
}
class Observe {
constructor(data) {
// 专门为数组
this.dep = new Dep()
// 每个对象都有__obj 属性,返回当前的observe实例
Object.defineProperty(data, '__ob__', {
get: () => this
})
// 数组 重写push 方法
if (Array.isArray()) {
// 只能拦截数组方法 数组的每一个项还需要观测
data._proto = arrayMethod
// 观测数组的每一个项
observerArray(data)
} else {
// 对象
// data 就是我们 定义的 vm._data 的数据
this.walk(data)
}
}
walk(data) {
let keys = Object.keys(data);
for (let i = 0; i < keys.length; i++) {
let key = keys[i]; // key
let value = data[keys[i]]; // value
defineReactive(data, key, value)
}
}
}
export default Observe;
https://gitee.com/guangzhou110/handwritten_vue
来源:oschina
链接:https://my.oschina.net/u/4342549/blog/3230496