Search code examples
vue.jsvuejs2vue-componentvue-reactivity

vue.js reactivity how dependency class might have many watcher subscribers


As you know, for each data property, there's a new Dep class created. Each Dep class has subscribers of watchers.

I looked through vue.js source code and for each component, there's only ONE watcher class being created which also holds the render function(template of the component).

1) Could you describe the situation when and why data property of one of the components might have the Dep class which has more than one watcher class?

2) So can I sum up something like this: if we have a component which has 5 data properties. each of these 5 data properties has different Dep class instance. and each of those Dep class has the same Watcher and that watcher holds the component's render function. If state changes, one of those 5 Dep class's notify gets run and that notify runs its watcher's render function?


Solution

  • You may find this introduction useful:

    https://medium.com/dailyjs/tracing-or-debugging-vue-js-reactivity-the-computed-tree-9da0ba1df5f9

    As you've mentioned, each data property will have its own instance of Dep. Each Dep has a subs property that holds an array of subscribers. The subscribers in that array will all be instances of the Watcher class. If a data property changes then the corresponding Dep will notify each Watcher in its subs.

    Each Watcher also holds references back to its dependencies, in a property called deps. This is just an array of the Dep objects to which the Watcher is subscribed.

    You'll be able to see this in your browser developer tools. If you log a Vue instance you'll find a property called _watchers that holds all the watchers related to that component. Expanding their deps will lead you to the Dep objects, though it can be tricky to tell exactly which data property each Dep represents.

    The rendering process has a Watcher that it uses to track its data dependencies. You'll only get one of those per component instance.

    A Watcher is also created if you use watch or $watch. Again you'll be able to see these in _watchers.

    Computed properties have one Watcher each. Those will be present in the _watchers array but it's easier to see them in _computedWatchers.

    A key thing to note is that dependencies are flattened. If you use a computed property you'll actually just get a dependency on all the data properties that contributed to it. You can't form a direct dependency on the computed property itself.

    So to go back to your original question:

    1. Rendering, computed properties and watch will all contribute to the subs of a Dep. Computed properties will often contribute more subscribers than you might expect due to the flattening of the dependencies.
    2. Almost. The render function isn't called directly. When the Watcher for rendering is notified of a data change it will actually just add the component to a queue. That rendering queue won't be processed until the start of the next tick.