Heim  >  Artikel  >  Web-Frontend  >  So implementieren Sie die Reaktionsfähigkeit von vue2.0 (ausführliches Tutorial)

So implementieren Sie die Reaktionsfähigkeit von vue2.0 (ausführliches Tutorial)

亚连
亚连Original
2018-06-05 17:48:441768Durchsuche

In diesem Artikel werden hauptsächlich die grundlegenden Ideen zur Implementierung der Vue2.0-Reaktionsfähigkeit vorgestellt. Jetzt teile ich ihn mit Ihnen und gebe Ihnen eine Referenz.

Ich habe kürzlich den vue2.0-Quellcode über die Implementierung von Reaktionsfähigkeit gelesen. Der folgende Blog-Beitrag wird die Implementierungsideen von vue2.0 über Reaktionsfähigkeit durch einfachen Code wiederherstellen.

Beachten Sie, dass dies nur eine Wiederherstellung der Implementierungsidee ist. Die Implementierung verschiedener Details, wie z. B. die Überwachung von Datenoperationen in Arrays und die Objektverschachtelung, wird in diesem Beispiel nicht behandelt Für eine detailliertere Implementierung können Sie mehr darüber erfahren, indem Sie den Quellcode-Beobachterordner und die Statusdatei im Instanzordner lesen.

Zuerst definieren wir die Struktur des Vue-Objekts

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

Schritt 1: Ändern Sie die Eigenschaften unter Daten in „observable“

Verwenden Sie Object .defineProperty-Monitore Die Attribute get und set des Datenobjekts werden aufgerufen, wenn Daten gelesen und zugewiesen werden. Auf diese Weise kann die Zuweisung mit dem häufigsten Gleichheitszeichen ausgelöst werden.

//数据劫持,监控数据变化
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,
  configurable: true,
  get: ()=>{
   return val
  },
  set: newVal => {
   if(newVal === val)
    return
   val = newVal
  }
 })
}

Schritt 2: Implementieren Sie einen Nachrichtenabonnenten

Es ist ganz einfach. In dieses Array fügen wir den Abonnenten ein Rufen Sie einfach Ihre eigene Update-Methode auf

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

Jedes Mal, wenn die Set-Funktion aufgerufen wird, lösen wir eine Benachrichtigung aus, um das Update zu implementieren

Dann kommt das Problem. Wer sind Abonnenten? Ja, es ist Watcher. . Sobald dep.notify() die Abonnenten, also den Watcher, durchläuft, ruft er seine update()-Methode auf

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

Schritt 3: Implementieren Sie einen Watcher

Watcher Die Implementierung ist relativ einfach. Tatsächlich ist es der Vorgang, den wir ausführen müssen, wenn wir Datenänderungen durchführen

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

Schritt 4: Berühren Sie, um die Abhängigkeit zu erhalten

Wir haben das erreicht Die oben genannten drei Schritte: Datenänderungen können Aktualisierungen auslösen, aber das Problem besteht jetzt darin, dass wir den Beobachter nicht mit unseren Daten verknüpfen können.

Wir wissen, dass, nachdem das Attribut für Daten auf „defineReactive“ gesetzt wurde, eine Änderung des Werts für Daten das Setzen auslöst. Wenn wir dann den oberen Datenwert übernehmen, wird get ausgelöst. Sie können dies also nutzen und zunächst die folgende Renderfunktion ausführen, um zu erfahren, welche Datenunterstützung erforderlich ist, um die Ansicht zu aktualisieren und sie als Abonnent der Daten aufzuzeichnen.

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

Schließlich schauen wir uns die Verwendung eines Proxys an, um unseren Datenzugriff an das Vue-Objekt zu binden

 _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))

Das Folgende ist der vollständige Code der gesamten Instanz

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, {
   configurable: true,
   enumerable: true,
   get: function proxyGetter () {
    return self._data[key]
   },
   set: function proxySetter (val) {
    self._data[key] = val
   }
  })
 }
 _update() {
  console.log("我需要更新");
  this._render.call(this)
 }
 _render() {
  this._bindText();
 }

 _bindText() {
  let textDOMs=this.$el.querySelectorAll('[v-text]'),
  bindText;
  for(let i=0;i defineReactive(value, key, value[key] , cb))
}

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()
  }
 })
}
function watch(vm, exp, cb){
 Dep.target = 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)
 }
 notify() {
  this.subs.forEach((watcher) => watcher.cb())
 }
}
Dep.target = null; 
var demo = new Vue({
 el: '#demo',
 data: {
 text: "hello world"
 }
 })
 
setTimeout(function(){
 demo.text = "hello new world"
 
}, 1000)

 
  

Oben ist die gesamte Idee des gesamten datengesteuerten Teils von Vue. Wenn Sie mehr über die Implementierung im Detail erfahren möchten, empfiehlt es sich, einen tieferen Blick auf diesen Teil des Vue-Codes zu werfen.

Ich habe das Obige für Sie zusammengestellt und hoffe, dass es Ihnen in Zukunft hilfreich sein wird.

Verwandte Artikel:

Verwenden Sie vue+element-ui+ajax, um ein Beispiel einer Tabelle zu implementieren

Verwenden Sie live -server How Um einen lokalen Server einzurichten und automatisch zu aktualisieren, welche spezifischen Methoden gibt es?

Lösen Sie das Problem, dass Browser niedrigerer Versionen den Import von es6 nicht unterstützen

Das obige ist der detaillierte Inhalt vonSo implementieren Sie die Reaktionsfähigkeit von vue2.0 (ausführliches Tutorial). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn