Home  >  Article  >  Web Front-end  >  A brief analysis of vue data binding

A brief analysis of vue data binding

高洛峰
高洛峰Original
2017-01-20 10:28:361130browse

Foreword: Recently, the team needed to do a sharing, but I didn’t know how to share it. Finally, I thought that I had always wanted to study the vue source code, and I just "took this opportunity" to study it today.

There are already a lot of articles on Vue data binding on the Internet, but writing it yourself, typing a demo and reading other people's articles are completely different, so...the porters are coming

Currently, there are three main ways to implement data binding:

1. Dirty value check (angular.js) Polling to detect data changes

DOM events, such as users entering text, clicking buttons, etc. . (ng-click)

XHR response event ($http)

Browser Location change event ($location)

Timer event ($timeout, $interval)

Execute $digest() or $apply()

2. Object.defineProperty hijacks the get and set of the object to monitor the data. (vue)

3. Publisher/subscriber mode realizes automatic synchronization of data and views

Advantages of Object.defineProperty

"Dirty value detection"-data changes Finally, a test is performed on the binding relationship between all data and views to identify whether any data has changed. If any changes are processed, it may further cause changes in other data, so this process may cycle several times until it is no longer After data changes occur, the changed data is sent to the view, and the page is updated to display

Object.defineProperty(). Monitor the operations on the data and automatically trigger data synchronization. Moreover, since synchronization is triggered on different data, changes can be accurately sent to the bound view instead of performing a test on all data.

Usage of Object.defineProperty

var a = {};

Object.defineProperty(a, "b", {

 set: function (newValue) {

 console.log("我被赋值了!" + newValue);

 },

 get: function () {

 console.log("我被取值了!");

 return 2
 }
})

a.b = 3; //我被赋值了!

console.log(a.b); //我被取值了! //打印 2

As can be seen from the above example, Object.defineProperty passes 3 parameters

The first one: a object

Second one: b attribute in a object

Third one: There are many properties, including useful value, set, get, configurable

Data binding principle :

1. Implement a data listener Observer to monitor all 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, scans and parses the instructions of each element node, replaces the data according to the instruction template

3, implements a dep array, can subscribe to and receive notifications of each attribute change, and execute the corresponding instructions bound Callback function, update view

1. Implement observer

var data = {name: 'beidan'};

observe(data);

data.name = 'test'; // 监听到值变化了 beidan 变成 test

function observe(data) {

 if (!data || typeof data !== 'object') {

 return;

 }

 // 取出所有属性遍历

 Object.keys(data).forEach(function(key) {

  defineReactive(data, key, data[key]);

 });
}
function defineReactive(data, key, val) {


 Object.defineProperty(data, key, {

 enumerable: true, // 可枚举

  configurable: false, // 不能再define
  get: function() {
 
   return val;

  },

  set: function(newVal) {
 
   console.log('监听到值变化了 ', val, ' 变成 ', 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('监听到值变化了 ', val, ' 变成 ', newVal);
  val = newVal;
  dep.notify(val); // 通知所有订阅者
 }
 });
}


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(&#39;v-text&#39;);
 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

 });

 }
},

The above is the entire content of this article. I hope that the content of this article can bring some help to everyone's study or work. I also hope to support the PHP Chinese website!

For more articles related to brief analysis of vue data binding, please pay attention to the PHP Chinese website!


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn