In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article focuses on "how to understand vue2.0 responsive architecture". Interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn how to understand the vue2.0 responsive architecture.
Say that all the properties under data become observable
Let's look at the code first.
Class Vue {constructor (options) {this.$options = options this._data = options.data observer (options.data, this._update) this._update ()} _ update () {this.$options.render ()}} function observer (value, cb) {Object.keys (value). ForEach ((key) = > defineReactive (value, key, value [key]) Cb)} function defineReactive (obj, key, val, cb) {Object.defineProperty (obj, key, {enumerable: true, configurable: true, get: () = > {}, set:newVal= > {cb ()}})} var demo = new Vue ({el:'# demo' Data: {text: 123,}, render () {console.log ("I want render")}}) setTimeout (function () {demo._data.text = 444}, 3000)
In order to demonstrate that we will only consider the simplest case, it may be easy to understand if we look at the vue source code analysis of how to implement observer and watcher, but it doesn't matter, let's repeat in a few words, the function of this code is to
Var demo = new Vue ({el:'# demo', data: {text: 123,}, render () {console.log ("I want render")}})
All the attributes in data in data are placed in observer, and then the properties in data, such as text, cause the _ update () function to be called and then re-rendered. How do you do that? we know that you have to change when you assign a value, right? when I assign a value to the text under data, the set function will trigger, and calling _ update at this time will ok, but
SetTimeout (function () {demo._data.text = 444}, 3000)
Demo._data.text is not as cool as demo.text. It doesn't matter. We'll add an agent.
_ proxy (key) {const self = this Object.defineProperty (self, key, {configurable: true, enumerable: true, get: function proxyGetter () {return self._ data [key]}, set: function proxySetter (val) {self._ data [key] = val}})}
Then add the following sentence to Vue's constructor
Object.keys (options.data) .forEach (key = > this._proxy (key))
* at this point, we will find a problem. A change in the value of any attribute in data will cause
Triggered by _ update and then re-rendered, the attribute is obviously not accurate enough.
The second step is to explain in detail why the steps are not accurate enough.
For example, consider the following code
New Vue ({template: `name: {{name}} age: {{age}} `, data: {name: 'js', age: 24, height: 180}) setTimeout (function () {demo.height = 181}, 3000)
Only two attributes on data, name and age, are used in template, but when I change height, will re-rendering be triggered with the code of step * *? Yes, but you don't need to trigger re-rendering, that's the problem!
The third step is how to solve the above problems
Talk about virtual DOM briefly.
First of all, the template*** is compiled into the render function (let's not expand on how to do it, but I'll talk about it later), and then the execution of the render function will get a virtual DOM. In order to understand, we write the simplest virtual DOM.
Function VNode (tag, data, children, text) {return {tag: tag, data: data, children: children Text: text}} class Vue {constructor (options) {this.$options = options const vdom = this._update () console.log (vdom)} _ update () {return this._render.call (this)} _ render () {const vnode = this.$options.render.call (this) return vnode} _ _ hype _ (tag) Attr, children) {return VNode (tag, attr, children.map ((child) = > {if (typeof child = 'string') {return VNode (undefined, child)} else {return child}}))} _ toString__ (val) {return val = = null?': typeof val = = 'object'? JSON.stringify (val, null, 2): String (val) }} var demo = new Vue ({el:'# demo', data: {text: "before",}, render () {return this.__h__ ('div', {}, [this.__h__ (' span', {}) [this.__toString__ (this.text)])])}})
If we run it, he will output
{tag: 'div', data: {}, children: [{tag:' span', data: {}, children: [{children: undefined, data: undefined, tag: undefined, text:''/ / string before normally Because we don't write the agent code for demonstration purposes, it's empty}]}}.
This is the simplest virtual DOM,tag is the html tag signature, data contains attributes on tags such as class and style, childen is the child node, let's not expand on the virtual DOM.
Back to the beginning, that is, I need to know which variables in the vue instance are dependent on in the render function (just consider render, because template will also help you compile to render). The description is a bit of a mouthful, so let's look at the code.
Var demo = new Vue ({el:'# demo', data: {text: "before", name: "123", age: 23}, render () {return this.__h__ ('div', {}, [this.__h__ (' span', {}) [this.__toString__ (this.text)])])}})
Like this code, the render function actually depends only on text, not on name and age, so we just need to change the text
We automatically trigger the render function to generate a virtual DOM and ok (all that is left is that the virtual DOM is compared with the last virtual DOM, and then the real DOM is operated, so we can only talk about it later), so let's formally consider what to do.
Step three, 'touch' gets the dependency.
Going back to the top figure, we know that after the property on data sets defineReactive, changing the value on data triggers set.
So if we take the upper value of data, it will trigger get.
Yes, we can tamper with it. Let's execute render first. Let's see which attributes on data trigger get. Won't we know which variables render depends on on data?
And then we tamper with these variables, and every time these variables change, we trigger render.
The above steps are simply summed up in four sub-steps to calculate dependencies.
(in fact, not only render, but the change of any variable is caused by the change of other variables, which can be used in the above method, that is, the principle of computed and watch, which is also the core of mobx.)
* step
We write a class that relies on collection, and every object on data may be dependent on the render function, so each property is in the defineReactive.
Initialize it at the right time, and that's what it looks like in short.
Class Dep {constructor () {this.subs = []} add (cb) {this.subs.push (cb)} notify () {console.log (this.subs) This.subs.forEach ((cb) = > cb ()}} function defineReactive (obj, key, val, cb) {const dep = new Dep () Object.defineProperty (obj, key, {/ / omitted})}
Then, when the render function is executed to touch' the dependent variable get is executed, and then we can add the render function to the subs.
When we, set, we execute notify to execute all the functions in the subs array, including the execution of render.
At this point, the whole picture is completed, so let's show all the code.
Function VNode (tag, data, children, text) {return {tag: tag, data: data, children: children Text: text}} class Vue {constructor (options) {this.$options = options this._data = options.data Object.keys (options.data) .forEach (key = > this._proxy (key)) observer (options.data) const vdom = watch (this, this._render.bind (this) This._update.bind (this)) console.log (vdom)} _ proxy (key) {const self = this Object.defineProperty (self, key, {configurable: true, enumerable: true, get: function proxyGetter () {return self._ data [key]} Set: function proxySetter (val) {self._data.text = val}})} _ update () {console.log ("I need to update") Const vdom = this._render.call (this) console.log (vdom) } _ render () {return this.$options.render.call (this)} _ _ hackers _ (tag, attr, children) {return VNode (tag, attr, children.map ((child) = > {if (typeof child = 'string') {return VNode (undefined, undefined, undefined) Child)} else {return child}})} _ toString__ (val) {return val = = null?'': typeof val = 'object'? JSON.stringify (val, null, 2): String (val) }} function observer (value, cb) {Object.keys (value). ForEach ((key) = > defineReactive (value, key, value [key], cb))} function defineReactive (obj, key, val, cb) {const dep = new Dep () Object.defineProperty (obj, key, {enumerable: true, configurable: true Get: () = > {if (Dep.target) {dep.add (Dep.target)} return val}, set: newVal = > {if (newVal = val) return val = newVal dep.notify ()})} function watch (vm, exp Cb) {Dep.target = cb return exp ()} class Dep {constructor () {this.subs = []} add (cb) {this.subs.push (cb)} notify () {this.subs.forEach ((cb) = > cb ())} Dep.target = null var demo = new Vue ({el:'# demo' Data: {text: "before",}, render () {return this.__h__ ('div', {}, [this.__h__ (' span', {}, [this.__toString__ (this.text)])}}) setTimeout (function () {demo.text = "after"}, 3000)
Let's take a look at the running results.
Okay, let's explain Dep.target because we have to distinguish between ordinary get and get when looking for dependencies.
All when we are looking for dependencies, we will
Function watch (vm, exp, cb) {Dep.target = cb return exp ()}
Dep.target assignment, which is equivalent to flag, and then get
Get: () = > {if (Dep.target) {dep.add (Dep.target)} return val}, at this point, I believe you have a deeper understanding of "how to understand vue2.0 responsive architecture". You might as well do it in practice! Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.