Original link to my blog, welcome STAR.
First of all, do you have any friends with vscode? Recommend a magic font, since the use of this font, typing efficiency is sky high. Here’s how it looks:
There are many others, not to mention them all. Did you catch your eye? No. I’ll come back to you later.
The recommended article is from here. Reading this article will help you understand the structure of the Vue application. Although it is version 1.0, version 2.0 retains most of the 1.0 API.
In this article, I will be a summary of my study of Vue in these months.
Train of thought
Vue and other MVVM ideas are similar:
The main purpose is to achieve three processes:
-
Observer: The Observer listens to data and provides the ability to subscribe to changes to a data item. Object. DefineProperty is used to convert every attribute in data into getter/setter, intercepting Object assignment and value operation.
-
Compiler: Parse template into the render() method;
-
Watcher: Compiler’s parsing results are combined with the Observer to receive notification when the Observer is listening for changes in data, which in turn triggers re-render and re-renders the DOM.
new Vue
Let’s start with New Vue,
The diagram above is a life cycle diagram provided by the official website, which mainly consists of four processes:
- Create: Runs when new Vue() creates a Vue object.
- Mount: Generates vNodes according to EL, template, render, etc., completes diff algorithm and mounts to DOM.
- Updata: The DOM is re-rendered when the data changes.
- Destory: Runs when Vue is destroyed.
Now, let’s go into the source code and analyze the implementation:
- Create: Run first
new vue()
Will enter_init.
The key part of the code is as follows:
BeforeCreate and Created only have initState, which is used to implement data Observer and Event /watcher.
- In the Mount:
_init
Finally, it will runvm.$mount
Methods:
$mount vm.$mount Finally render() is performed to give vNodes and the real DOM after DIFF algorithm.
-
Update: After DOM, the Update method is used:
vm._watcher = new Watcher(vm, () => { vm._update(vm._render(), hydrating) }, noop)Copy the code
The above is represented by a sequence diagram:
Deep Responsive Principle (Observer, Watcher)
An important feature of the MVVM framework is that it automatically updates the corresponding DOM nodes when data changes. How is Vue implemented?
This is a picture from the official website.
As mentioned earlier, the initState() method is run between the beforeCreate and Created lifecycle hook functions.
InitState () :
In this method, properties like props, data, computed, etc., are converted to getters/setters using Object.defineProperty.
We use initData() as an example:
Proxy (vm, “_data”, keys[I]) sets vm._data as the proxy, implementing vm.a === vm._data.
Observe (data, this) at the end of initData().
In observe(), both convert to getter/setter.
Object.defineProperty(obj, key, {
enumerable: true.configurable: true.get: function reactiveGetter () {
const value = getter ? getter.call(obj) : val
Target is the getter fired by the Vue's internal dependency collection process
// Dep.depend () to add watcher(the actual value of dep.target) to the subs array of deP
For other times, such as in the DOM event callback function, the getter triggered by accessing this variable does not need to perform the dependency collection and simply returns the value
if (Dep.target) {
dep.depend()
if (childOb) {
// If value generates an OB instance during Observe, make ob's DEP collect dependencies as well
childOb.dep.depend()
}
if (isArray(value)) {
// If the array element is also an object, their observe procedure also generates an OB instance
dependArray(value)
}
}
return value
},
set: function reactiveSetter (newVal) {
var value = getter ? getter.call(obj) : val
if (newVal === value) {
return
}
if (setter) {
setter.call(obj, newVal)
} else {
val = newVal
}
// Observe this new data
childOb = observe(newVal)
// Notify deP for data update.
dep.notify()
}
})Copy the code
At this point, Observer listening is complete, and if the data is updated, we call dep.notify() :
Dep.notify (), update() :
The queueWatcher() method is used in update() :
QueueWatcher (), whose purpose is to execute run() via nextTicker:
In run(), we call this.get() :
In the get() method, the this.getter() method is run to update the DOM.
What is the this.getter() method?
Then there is the second argument to the new Watcher() mentioned above.
vm._watcher = new Watcher(vm, () => {
vm._update(vm._render(), hydrating)
}, noop)Copy the code
After the new Watcher construction is complete, this.get() is called, which fires this.getter(), and the method fires DOM updates.
For details, see watcher.js:
Screenshot of a key code section:
The above, represented by a sequence diagram, is:
To sum up the above:
- First of all,
_init
, the use of attributesObject.defineProperty
To convert the property togetter/setter
In thesetter
Method, will calldep.notify()
. - right
vm
Set up thenew Watcher
. data
Update data when changing.
To the end.