About the Vue. Js
Vue. Js is an MVVM framework that is quick and easy to use, and updates views as data is modified in a responsive manner. The responseful principle of vue.js relies on Object.defineProperty, as mentioned in the vue.js documentation, which is why vue.js does not support IE8 and earlier browsers. Vue listens for changes in data by setting setter/getter methods for object properties, relies on the getter for collection, and each setter method is an observer that notifies the subscriber to update the view when the data changes.
Turns data into an observable
So how does Vue turn all properties under all data into observables?
function observe(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: () = >{
/ *... Dependency collection etc.... * /
/*Github:https://github.com/answershuto*/
return val
},
set:newVal= > {
val = newVal;
cb();/* The subscriber receives a callback to the message */}})}class Vue {
constructor(options) {
this._data = options.data;
observe(this._data, options.render)
}
}
let app = new Vue({
el: '#app'.data: {
text: 'text'.text2: 'text2'
},
render(){
console.log("render"); }})Copy the code
To make it easier to understand, let’s first consider the simplest case, leaving out arrays and so on, as shown in the code above. Observe is called in initData to set the Vue data to observable. Set is triggered when the _data data changes, performing a callback to the subscriber (render in this case).
The problem is that the app._data.text operation is required to trigger set. For the sake of laziness, we need a convenient way to trigger a set to redraw the view via app.text directly. Then you need to use proxies.
The agent
We can execute a proxy for data in Vue’s constructor. This allows us to delegate the properties on data to the VM instance.
_proxy.call(this, options.data);/* In the constructor */
* / / * agent
function _proxy (data) {
const that = this;
Object.keys(data).forEach(key= > {
Object.defineProperty(that, key, {
configurable: true.enumerable: true.get: function proxyGetter () {
return that._data[key];
},
set: function proxySetter (val) { that._data[key] = val; }})}); }Copy the code
App._data.text can be used instead of app._data.text.