Analysis of vue data binding
- 2021-07-12 04:54:09
- OfStack
Recently, the team needs to do a sharing, and they don't know how to share. Finally, thinking about the previous 1 straight want to study 1 vue source code, today just "take this opportunity" to study 1.
There are a lot of articles about vue data binding on the Internet, but it is completely different to write and knock demo once and read other people's articles. so … … The porter is here
At present, there are mainly three ways to implement data binding:
1. Dirty value check (angular. js) polling to detect data changes
DOM events, such as user entering text, clicking buttons, and so on. (ng-click)
XHR Response Event ($http) Browser Location Change Event ($location) Timer Events ($timeout, $interval) Execute $digest () or $apply ()2. Object. defineProperty hijacks get and set of objects, thus realizing data monitoring. (vue)
3. Publish/Subscriber Mode realizes automatic synchronization between data and view
Object. Advantages of defineProperty
"Dirty value detection"-after the data changes, For all the data and view binding relationship to detect once, identify whether there is a change in the data, change processing, may lead to other data changes, so this process may be cycled several times, 1 until no more data changes occurred, the changed data will be sent to the view, update the page presentation Object. defineProperty () monitors operations on data and automatically triggers data synchronization. Moreover, because synchronization is triggered on different data, changes can be accurately sent to the bound view, instead of performing one detection on all data.Object. Usage of defineProperty
var a = {};
Object.defineProperty(a, "b", {
set: function (newValue) {
console.log(" I've been assigned a value! " + newValue);
},
get: function () {
console.log(" I've been valued! ");
return 2
}
})
a.b = 3; // I've been assigned a value!
console.log(a.b); // I was valued ! // Print 2
From the above example, we can see that Object. defineProperty has three parameters
Number 1: a object
Second: b attribute in a object
Third: There are many attributes, listing useful value, set, get and configurable
Data binding principles:
1. Implement a data listener Observer to monitor all the attributes of the data object. If there is any change, get the latest value and notify the dep array
2. Implement an instruction parser Compile, which scans and parses the instructions of each element node and replaces the data according to the instruction template
3. Implement an dep array, which can subscribe and receive the notification of each attribute change, execute the corresponding callback function bound by instructions, and update the view
1. Implement observer
var data = {name: 'beidan'};
observe(data);
data.name = 'test'; // Listen to the value change beidan Become test
function observe(data) {
if (!data || typeof data !== 'object') {
return;
}
// Fetch all attributes to traverse
Object.keys(data).forEach(function(key) {
defineReactive(data, key, data[key]);
});
}
function defineReactive(data, key, val) {
Object.defineProperty(data, key, {
enumerable: true, // Enumerable
configurable: false, // Can no longer define
get: function() {
return val;
},
set: function(newVal) {
console.log(' Listen to the value change ', val, ' Become ', newVal);
val = newVal;
}
});
}
2. Maintain an array
function Dep() {
this.subs = [];
}
Dep.prototype = {
addSub: function (sub) {
this.subs.push(sub);
},
notify: function (val) {
this.subs.forEach(function (sub) {
sub.update(val)
});
}
};
function defineReactive(data, key, val) {
Object.defineProperty(data, key, {
...
set: function(newVal) {
if (val === newVal) return;
console.log(' Listen to the value change ', val, ' Become ', newVal);
val = newVal;
dep.notify(val); // Notify all subscribers
}
});
}
3. compile
bindText: function () {
var textDOMs = this.el.querySelectorAll('[v-text]'),
bindText,_context = this;
for (var i = 0; i < textDOMs.length; i++) {
bindText = textDOMs[i].getAttribute('v-text');
textDOMs[i].innerHTML = this.data[bindText];
var val = textDOMs[i]
var up = function (text) {
val.innerText = text
}
_context.dep.addSub({
value: textDOMs[i],
update: up
});
}
},
Finally, attach the source code github https://github.com/beidan/vue_bind
Reference link:
https://www.ofstack.com/article/103297.htm
https://www.ofstack.com/article/99129.htm