Table of Contents
1. Principle " >1. Principle
2. Implement the " >2. Implement the
Home Web Front-end JS Tutorial Analysis of Vue binding issues

Analysis of Vue binding issues

Jun 07, 2018 am 10:40 AM

This time I will bring you an analysis of Vue binding issues and what are the precautions for Vue binding. The following is a practical case, let's take a look.

1. Principle

# I believe everyone is familiar with the principle of Vue’s two-way data binding, mainly through the defineProperty of the Object object Attributes are implemented by rewriting the set and get functions of data. The principle will not be described too much here. The main purpose is to implement an example. In order to make the code clearer, only the most basic content will be implemented here, mainly implementing the three commands v-model, v-bind and v-click. Other commands can also be supplemented by yourself.

Add a picture from the Internet

2. Implement the

page structure Very simple, as follows

<p id="app">
 <form>
  <input type="text" v-model="number">
  <button type="button" v-click="increment">增加</button>
 </form>
 <h3 v-bind="number"></h3>
 </p>
Copy after login

contains:

1. An input, using the v-model command
2. A button, using the v-click command
3. An h3, Use the v-bind directive.

We will finally use our two-way data binding in a way similar to vue, adding comments combined with our data structure

var app = new myVue({
  el:'#app',
  data: {
  number: 0
  },
  methods: {
  increment: function() {
   this.number ++;
  },
  }
 })
Copy after login

First we need to define a myVue constructor:

function myVue(options) {
}
Copy after login

In order to initialize this constructor, add an _init attribute to it

function myVue(options) {
 this._init(options);
}
myVue.prototype._init = function (options) {
 this.$options = options; // options 为上面使用时传入的结构体,包括el,data,methods
 this.$el = document.querySelector(options.el); // el是 #app, this.$el是id为app的Element元素
 this.$data = options.data; // this.$data = {number: 0}
 this.$methods = options.methods; // this.$methods = {increment: function(){}}
 }
Copy after login

Next implement the _obverse function, process the data, and rewrite the set and get functions of data

And transform the _init function

myVue.prototype._obverse = function (obj) { // obj = {number: 0}
 var value;
 for (key in obj) { //遍历obj对象
  if (obj.hasOwnProperty(key)) {
  value = obj[key]; 
  if (typeof value === 'object') { //如果值还是对象,则遍历处理
   this._obverse(value);
  }
  Object.defineProperty(this.$data, key, { //关键
   enumerable: true,
   configurable: true,
   get: function () {
   console.log(`获取${value}`);
   return value;
   },
   set: function (newVal) {
   console.log(`更新${newVal}`);
   if (value !== newVal) {
    value = newVal;
   }
   }
  })
  }
 }
 }
 myVue.prototype._init = function (options) {
 this.$options = options;
 this.$el = document.querySelector(options.el);
 this.$data = options.data;
 this.$methods = options.methods;
 this._obverse(this.$data);
 }
Copy after login

Next we write an instruction class Watcher to bind the update function to update the DOM elements

function Watcher(name, el, vm, exp, attr) {
 this.name = name;   //指令名称,例如文本节点,该值设为"text"
 this.el = el;    //指令对应的DOM元素
 this.vm = vm;    //指令所属myVue实例
 this.exp = exp;   //指令对应的值,本例如"number"
 this.attr = attr;   //绑定的属性值,本例为"innerHTML"
 this.update();
 }
 Watcher.prototype.update = function () {
 this.el[this.attr] = this.vm.$data[this.exp]; //比如 H3.innerHTML = this.data.number; 当number改变时,会触发这个update函数,保证对应的DOM内容进行了更新。
 }
Copy after login

Update the _init function and _obverse function

myVue.prototype._init = function (options) {
 //...
 this._binding = {}; //_binding保存着model与view的映射关系,也就是我们前面定义的Watcher的实例。当model改变时,我们会触发其中的指令类更新,保证view也能实时更新
 //...
 }
 myVue.prototype._obverse = function (obj) {
 //...
  if (obj.hasOwnProperty(key)) {
  this._binding[key] = { // 按照前面的数据,_binding = {number: _directives: []}                                     
   _directives: []
  };
  //...
  var binding = this._binding[key];
  Object.defineProperty(this.$data, key, {
   //...
   set: function (newVal) {
   console.log(`更新${newVal}`);
   if (value !== newVal) {
    value = newVal;
    binding._directives.forEach(function (item) { // 当number改变时,触发_binding[number]._directives 中的绑定的Watcher类的更新
    item.update();
    })
   }
   }
  })
  }
 }
 }
Copy after login

So how to bind the view to the model? Next, we define a _compile function to parse our instructions (v-bind, v-model, v-clickde), etc., and bind the view and model in the process.

 myVue.prototype._init = function (options) {
 //...
 this._complie(this.$el);
 }
myVue.prototype._complie = function (root) { root 为 id为app的Element元素,也就是我们的根元素
 var _this = this;
 var nodes = root.children;
 for (var i = 0; i < nodes.length; i++) {
  var node = nodes[i];
  if (node.children.length) { // 对所有元素进行遍历,并进行处理
  this._complie(node);
  }
  if (node.hasAttribute(&#39;v-click&#39;)) { // 如果有v-click属性,我们监听它的onclick事件,触发increment事件,即number++
  node.onclick = (function () {
   var attrVal = nodes[i].getAttribute(&#39;v-click&#39;);
   return _this.$methods[attrVal].bind(_this.$data); //bind是使data的作用域与method函数的作用域保持一致
  })();
  }
  if (node.hasAttribute(&#39;v-model&#39;) && (node.tagName == &#39;INPUT&#39; || node.tagName == &#39;TEXTAREA&#39;)) { // 如果有v-model属性,并且元素是INPUT或者TEXTAREA,我们监听它的input事件
  node.addEventListener(&#39;input&#39;, (function(key) { 
   var attrVal = node.getAttribute(&#39;v-model&#39;);
   //_this._binding[&#39;number&#39;]._directives = [一个Watcher实例]
   // 其中Watcher.prototype.update = function () {
   // node[&#39;vaule&#39;] = _this.$data[&#39;number&#39;]; 这就将node的值保持与number一致
   // }
   _this._binding[attrVal]._directives.push(new Watcher( 
   &#39;input&#39;,
   node,
   _this,
   attrVal,
   &#39;value&#39;
   ))
   return function() {
   _this.$data[attrVal] = nodes[key].value; // 使number 的值与 node的value保持一致,已经实现了双向绑定
   }
  })(i));
  } 
  if (node.hasAttribute(&#39;v-bind&#39;)) { // 如果有v-bind属性,我们只要使node的值及时更新为data中number的值即可
  var attrVal = node.getAttribute(&#39;v-bind&#39;);
  _this._binding[attrVal]._directives.push(new Watcher(
   &#39;text&#39;,
   node,
   _this,
   attrVal,
   &#39;innerHTML&#39;
  ))
  }
 }
 }
Copy after login

So far, we have implemented a simple two-way binding function of vue, including three instructions: v-bind, v-model, and v-click. The effect is as shown below

Attached is the full code, less than 150 lines



 myVue



 <p id="app">
 <form>
  <input type="text" v-model="number">
  <button type="button" v-click="increment">增加</button>
 </form>
 <h3 v-bind="number"></h3>
 </p>

<script>
 function myVue(options) {
 this._init(options);
 }
 myVue.prototype._init = function (options) {
 this.$options = options;
 this.$el = document.querySelector(options.el);
 this.$data = options.data;
 this.$methods = options.methods;
 this._binding = {};
 this._obverse(this.$data);
 this._complie(this.$el);
 }
 myVue.prototype._obverse = function (obj) {
 var value;
 for (key in obj) {
  if (obj.hasOwnProperty(key)) {
  this._binding[key] = {                                       
   _directives: []
  };
  value = obj[key];
  if (typeof value === 'object') {
   this._obverse(value);
  }
  var binding = this._binding[key];
  Object.defineProperty(this.$data, key, {
   enumerable: true,
   configurable: true,
   get: function () {
   console.log(`获取${value}`);
   return value;
   },
   set: function (newVal) {
   console.log(`更新${newVal}`);
   if (value !== newVal) {
    value = newVal;
    binding._directives.forEach(function (item) {
    item.update();
    })
   }
   }
  })
  }
 }
 }
 myVue.prototype._complie = function (root) {
 var _this = this;
 var nodes = root.children;
 for (var i = 0; i < nodes.length; i++) {
  var node = nodes[i];
  if (node.children.length) {
  this._complie(node);
  }
  if (node.hasAttribute(&#39;v-click&#39;)) {
  node.onclick = (function () {
   var attrVal = nodes[i].getAttribute(&#39;v-click&#39;);
   return _this.$methods[attrVal].bind(_this.$data);
  })();
  }
  if (node.hasAttribute(&#39;v-model&#39;) && (node.tagName == &#39;INPUT&#39; || node.tagName == &#39;TEXTAREA&#39;)) {
  node.addEventListener(&#39;input&#39;, (function(key) {
   var attrVal = node.getAttribute(&#39;v-model&#39;);
   _this._binding[attrVal]._directives.push(new Watcher(
   &#39;input&#39;,
   node,
   _this,
   attrVal,
   &#39;value&#39;
   ))
   return function() {
   _this.$data[attrVal] = nodes[key].value;
   }
  })(i));
  } 
  if (node.hasAttribute(&#39;v-bind&#39;)) {
  var attrVal = node.getAttribute(&#39;v-bind&#39;);
  _this._binding[attrVal]._directives.push(new Watcher(
   &#39;text&#39;,
   node,
   _this,
   attrVal,
   &#39;innerHTML&#39;
  ))
  }
 }
 }
 function Watcher(name, el, vm, exp, attr) {
 this.name = name;   //指令名称,例如文本节点,该值设为"text"
 this.el = el;    //指令对应的DOM元素
 this.vm = vm;    //指令所属myVue实例
 this.exp = exp;   //指令对应的值,本例如"number"
 this.attr = attr;   //绑定的属性值,本例为"innerHTML"
 this.update();
 }
 Watcher.prototype.update = function () {
 this.el[this.attr] = this.vm.$data[this.exp];
 }
 window.onload = function() {
 var app = new myVue({
  el:&#39;#app&#39;,
  data: {
  number: 0
  },
  methods: {
  increment: function() {
   this.number ++;
  },
  }
 })
 }
</script>
Copy after login

I believe you have mastered the method after reading the case in this article, please pay attention for more exciting things Other related articles on php Chinese website!

Recommended reading:

How to use JS to obtain the city and geographical location of the user

Use classes in ES6 to imitate Vue. Out of two-way binding

The above is the detailed content of Analysis of Vue binding issues. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
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

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

What should I do if I encounter garbled code printing for front-end thermal paper receipts? What should I do if I encounter garbled code printing for front-end thermal paper receipts? Apr 04, 2025 pm 02:42 PM

Frequently Asked Questions and Solutions for Front-end Thermal Paper Ticket Printing In Front-end Development, Ticket Printing is a common requirement. However, many developers are implementing...

Demystifying JavaScript: What It Does and Why It Matters Demystifying JavaScript: What It Does and Why It Matters Apr 09, 2025 am 12:07 AM

JavaScript is the cornerstone of modern web development, and its main functions include event-driven programming, dynamic content generation and asynchronous programming. 1) Event-driven programming allows web pages to change dynamically according to user operations. 2) Dynamic content generation allows page content to be adjusted according to conditions. 3) Asynchronous programming ensures that the user interface is not blocked. JavaScript is widely used in web interaction, single-page application and server-side development, greatly improving the flexibility of user experience and cross-platform development.

Who gets paid more Python or JavaScript? Who gets paid more Python or JavaScript? Apr 04, 2025 am 12:09 AM

There is no absolute salary for Python and JavaScript developers, depending on skills and industry needs. 1. Python may be paid more in data science and machine learning. 2. JavaScript has great demand in front-end and full-stack development, and its salary is also considerable. 3. Influencing factors include experience, geographical location, company size and specific skills.

How to merge array elements with the same ID into one object using JavaScript? How to merge array elements with the same ID into one object using JavaScript? Apr 04, 2025 pm 05:09 PM

How to merge array elements with the same ID into one object in JavaScript? When processing data, we often encounter the need to have the same ID...

Is JavaScript hard to learn? Is JavaScript hard to learn? Apr 03, 2025 am 12:20 AM

Learning JavaScript is not difficult, but it is challenging. 1) Understand basic concepts such as variables, data types, functions, etc. 2) Master asynchronous programming and implement it through event loops. 3) Use DOM operations and Promise to handle asynchronous requests. 4) Avoid common mistakes and use debugging techniques. 5) Optimize performance and follow best practices.

How to achieve parallax scrolling and element animation effects, like Shiseido's official website?
or:
How can we achieve the animation effect accompanied by page scrolling like Shiseido's official website? How to achieve parallax scrolling and element animation effects, like Shiseido's official website? or: How can we achieve the animation effect accompanied by page scrolling like Shiseido's official website? Apr 04, 2025 pm 05:36 PM

Discussion on the realization of parallax scrolling and element animation effects in this article will explore how to achieve similar to Shiseido official website (https://www.shiseido.co.jp/sb/wonderland/)...

The Evolution of JavaScript: Current Trends and Future Prospects The Evolution of JavaScript: Current Trends and Future Prospects Apr 10, 2025 am 09:33 AM

The latest trends in JavaScript include the rise of TypeScript, the popularity of modern frameworks and libraries, and the application of WebAssembly. Future prospects cover more powerful type systems, the development of server-side JavaScript, the expansion of artificial intelligence and machine learning, and the potential of IoT and edge computing.

The difference in console.log output result: Why are the two calls different? The difference in console.log output result: Why are the two calls different? Apr 04, 2025 pm 05:12 PM

In-depth discussion of the root causes of the difference in console.log output. This article will analyze the differences in the output results of console.log function in a piece of code and explain the reasons behind it. �...

See all articles