Talking about the basic idea of implementing the vue2.0 response and the basic idea of vue2.0

Source: Internet
Author: User

Talking about the basic idea of implementing the vue2.0 response and the basic idea of vue2.0

I recently read vue2.0 source code about responsive implementation. The following blog posts will use simple code to restore vue2.0's Implementation ideas about responsive implementation.

Note: This is just a restoration of ideas. Implementation of various details, such as monitoring of data operations in the array and nesting of objects, will not be involved in this instance, to learn more about the implementation, read the observer folder of the source code and the state file in the instance folder.

First, we define the structure of the vue object.

class Vue {  constructor(options) {    this.$options = options;    this._data = options.data;    this.$el = document.querySelector(options.el);  }} 

Step 1: Change the attributes under data to observable

Use Object. defineProperty listens to the get and set attributes of Data Objects. When there is data read and value assignment, it calls the node command, so that the most common = equal sign value can be triggered.

// Data hijacking, monitoring data changes 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, retriable: true, get: () =>{ return val}, set: newVal =>{ if (newVal = val) return val = newVal }})}

Step 2: implement a message subscriber

Very easy. We maintain an array. This array is used by the subscriber. Once notify is triggered, the subscriber calls its own update method.

class Dep { constructor() {  this.subs = [] } add(watcher) {  this.subs.push(watcher) } notify() {  this.subs.forEach((watcher) => watcher.cb()) }} 

Every time the set function is called, notify is triggered to implement updates.

The problem arises. Who is the subscriber. Yes, Watcher .. Once dep. Y () is used, it traverses the subscriber, that is, Watcher, and calls its update () method.

function defineReactive(obj, key, val, cb) { const dep = new Dep() Object.defineProperty(obj, key, {  enumerable: true,  configurable: true,  get: ()=>{   return val  },  set: newVal => {   if(newVal === val)    return   val = newVal   dep.notify()  } })} 

Step 3: implement a Watcher

Watcher's implementation is relatively simple. It is actually the operation we want to perform when the data changes.

class Watcher { constructor(vm, cb) {  this.cb = cb  this.vm = vm } update(){  this.run() } run(){  this.cb.call(this.vm) } }

Step 4: touch gets dependency

In the preceding three steps, data changes can trigger updates. The problem is that we cannot associate watcher with our data.

After defineReactive is set for the attribute on data, modifying the value on data triggers the set. Then, get will be triggered when we take the data value. So we can use this to execute the following render function to know which data is required for view update and record it as the data subscriber.

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()  } })}

Finally, we can use a proxy to bind our data access to the vue object.

 _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   }  })}Object.keys(options.data).forEach(key => this._proxy(key))

The following is the complete code of the entire instance.

Class Vue {constructor (options) {this. $ options = options; this. _ data = options. data; this. $ el = document. querySelector (options. el); Object. keys (options. data ). forEach (key => this. _ proxy (key) observer (options. data) watch (this, this. _ render. bind (this), this. _ update. bind (this)} _ proxy (key) {const self = this Object. defineProperty (self, key, {retriable: true, enumerable: true, get: function proxyGetter () {return self. _ data [key]}, set: function proxySetter (val) {self. _ data [key] = val }})} _ update () {console. log ("I need to update"); this. _ render. call (this)} _ render () {this. _ bindText ();} _ bindText () {let textDOMs = this. $ el. querySelectorAll ('[v-text]'), bindText; for (let I = 0; I <textDOMs. length; I ++) {bindText = textDOMs [I]. getAttribute ('v-text'); let data = this. _ data [bindText]; if (data) {textDOMs [I]. innerHTML = data ;}}} 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, retriable: true, get: () =>{ if(Dep.tar get) {dep.add(Dep.tar get)} return val}, set: newVal => {if (newVal = val) return val = newVal dep. notify ()} function watch (vm, exp, cb) {Dep.tar get = new Watcher (vm, cb); return exp ()} class Watcher {constructor (vm, cb) {this. cb = cb this. vm = vm} update () {this. run ()} run () {this. cb. call (this. vm)} class Dep {constructor () {this. subs = []} add (watcher) {this. subs. push (watcher)} y () {this. subs. forEach (watcher) => watcher. cb () implements includep.tar get = null; var demo = new Vue ({el: '# demo', data: {text: "hello world"}) setTimeout (function () {demo. text = "hello new world"}, 1000) <body> <div id = "demo"> <div v-text = "text"> </div> </body>

The above is the overall idea of the entire vue data-driven part. If you want to learn more about the implementation, we recommend that you go deep into the vue code.

The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.