依赖收集

首先 要所有 option.data都会被proxy,

但 只有执行get的时候才会去收集依赖 ,
且一个组件只有一个watcher , 由于js是单线程,所以一个时刻只有一个watcher在执行

那么

  1. vue 是怎么收集依赖的呢
    可以当页面执行 mountComponent的时候 ,触发Object.defineProperty的函数
const dep = new Dep()

一个option.data 选项会有一个dep 实例

if (Dep.target) {
        dep.depend()
        if (childOb) {
          childOb.dep.depend()
          if (Array.isArray(value)) {
            dependArray(value)
          }
        }
      }      
 depend () {
    if (Dep.target) {
      Dep.target.addDep(this)
    }
  }
 addDep (dep: Dep) {
    const id = dep.id
    if (!this.newDepIds.has(id)) {
      this.newDepIds.add(id)
      this.newDeps.push(dep)
      if (!this.depIds.has(id)) {
        dep.addSub(this)
      }
    }
  }

addSub (sub: Watcher) {
    
    this.subs.push(sub)
  
  }

这里逻辑有一点绕 ,这里实际 是把watcher 收集到dep实例的subs 中, 用dep实例来管理watcher ,从而使 dep实例(观察目标)与 wacther(观察者)建立了联系,即与option.data选项建立了联系

由此可以预见的是如果是一个dep实例的subs 只有一个元素且 是同一个wacher

[Watcher]
0: Watcher
active: true
before: ƒ before()
cb: ƒ noop(a, b, c)
deep: false
depIds: Set(2) {15, 16}
deps: (2) [Dep, Dep]
dirty: false
expression: "function () {↵      debugger↵      vm._update(vm._render(), hydrating);↵    }"
getter: ƒ ()
id: 2
lazy: false
newDepIds: Set(0) {}
newDeps: []
sync: false
user: false
value: undefined
vm: VueComponent {_uid: 3, _isVue: true, $options: {}, _renderProxy: Proxy, _self: VueComponent,}
[Watcher]
0: Watcher
active: true
before: ƒ before()
cb: ƒ noop(a, b, c)
deep: false
depIds: Set(2) {15, 16}
deps: (2) [Dep, Dep]
dirty: false
expression: "function () {↵      debugger↵      vm._update(vm._render(), hydrating);↵    }"
getter: ƒ ()
id: 2
lazy: false
newDepIds: Set(0) {}
newDeps: []
sync: false
user: false
value: undefined
vm: VueComponent {_uid: 3, _isVue: true, $options: {}, _renderProxy: Proxy, _self: VueComponent,}

  1. 收集依赖收集 的是什么呢
    由上可见 ,vue 把 watcher 当 依赖收集起来了

  2. 如果页面是由组件组合 起来的 ,那 收集的依赖又是怎样的呢
    我的示例代码 是这样的:

 <div id="app">
    
    <hello-world></hello-world>
    {{name}}
    {{age}}
  </div>
HelloWorldHelloWorldHelloWorld {{name}} {{age}}
HelloWorldHelloWorldHelloWorldHelloWorld
```javascript 在这里插入代码片 ``` 输出的结果是: ```javascript Dep {id: 15, subs: Array(1)} [Watcher] 0: Watcher active: true before: ƒ before() cb: ƒ noop(a, b, c) deep: false depIds: Set(0) {} deps: [] dirty: false expression: "function () {↵ debugger↵ vm._update(vm._render(), hydrating);↵ }" getter: ƒ () id: 2 lazy: false newDepIds: Set(1) {15} newDeps: [Dep] sync: false user: false vm: VueComponent {_uid: 3, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …} ```
Dep {id: 16, subs: Array(1)}
[Watcher]0: Watcheractive: truebefore: ƒ before()cb: ƒ noop(a, b, c)deep: falsedepIds: Set(0) {}deps: []dirty: falseexpression: "function () {↵      debugger↵      vm._update(vm._render(), hydrating);↵    }"getter: ƒ ()id: 2lazy: falsenewDepIds: Set(2) {15, 16}newDeps: (2) [Dep, Dep]sync: falseuser: falsevm: VueComponent {_uid: 3, _isVue: true, $options: {}, _renderProxy: Proxy, _self: VueComponent,}__proto__: Objectlength: 1__proto__: Array(0)
Dep {id: 20, subs: Array(1)}
[Watcher]
0: Watcher
active: true
before: ƒ before()
cb: ƒ noop(a, b, c)
deep: false
depIds: Set(0) {}
deps: []
dirty: false
expression: "function () {↵      debugger↵      vm._update(vm._render(), hydrating);↵    }"
getter: ƒ ()
id: 3
lazy: false
newDepIds: Set(1) {20}
newDeps: [Dep]
sync: false
user: false
vm: VueComponent {_uid: 4, _isVue: true, $options: {}, _renderProxy: Proxy, _self: VueComponent,}
Dep {id: 21, subs: Array(1)}
[Watcher]
0: Watcher
active: true
before: ƒ before()
arguments: (...)
caller: (...)
length: 0
name: "before"
prototype: {constructor: ƒ}
__proto__: ƒ ()
[[FunctionLocation]]: vue.runtime.esm.js?2b0e:4083
[[Scopes]]: Scopes[4]
cb: ƒ noop(a, b, c)
deep: false
depIds: Set(0) {}
deps: []
dirty: false
expression: "function () {↵      debugger↵      vm._update(vm._render(), hydrating);↵    }"
getter: ƒ ()
id: 3
lazy: false
newDepIds: Set(2) {20, 21}
newDeps: (2) [Dep, Dep]
sync: false
user: false
vm: VueComponent {_uid: 4, _isVue: true, $options: {}, _renderProxy: Proxy, _self: VueComponent,}
__proto__: Object
length: 1
__proto__: Array(0)

可以看出当前只有一个watcher(3或4)在执行 ,而且收集依赖的顺序是先父后子

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值