vue2.0 の応答性を実装する方法 (詳細なチュートリアル)

亚连
リリース: 2018-06-05 17:48:44
オリジナル
1741 人が閲覧しました

この記事では主に vue2.0 の応答性を実装するための基本的なアイデアを紹介し、参考にしていきます。

最近、応答性の実装に関する vue2.0 のソース コードを読みました。次のブログ投稿では、簡単なコードによる応答性に関する vue2.0 の実装アイデアを復元します。

これは実装のアイデアを復元したものにすぎないことに注意してください。配列内のデータ操作の監視やオブジ​​ェクトのネストなど、さまざまな詳細の実装については、この例では説明しません。実装については、ソース コードのオブザーバー フォルダーとインスタンス フォルダー内の状態ファイルを読むことで詳しく知ることができます。

まず、最初に vue オブジェクトの構造を定義します

class Vue {
  constructor(options) {
    this.$options = options;
    this._data = options.data;
    this.$el = document.querySelector(options.el);
  }
}
ログイン後にコピー

ステップ 1: data の下のプロパティを observable に変更します

Object.defineProperty を使用して、データ オブジェクトの属性の取得と設定を監視します。 is data 操作の読み取りと割り当てを行う場合、ノードの命令が呼び出され、最も一般的な = 等号を使用した割り当てをトリガーできます。

//数据劫持,监控数据变化
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
  }
 })
}
ログイン後にコピー

ステップ 2: メッセージ サブスクライバ

の実装は非常に簡単です。この配列にサブスクライバを配置します。通知がトリガーされると、サブスクライバは独自の更新メソッド

class Dep {
 constructor() {
  this.subs = []
 }
 add(watcher) {
  this.subs.push(watcher)
 }
 notify() {
  this.subs.forEach((watcher) => watcher.cb())
 }
}
ログイン後にコピー

set を呼び出します。関数が呼び出されるたびに、更新を実装するために通知をトリガーします

すると、問題が発生します。購読者とは誰ですか。そう、ウォッチャーです。 。 dep.notify() がサブスクライバー、つまり Watcher を走査し、その update() メソッドを呼び出します

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()
  }
 })
}
ログイン後にコピー

ステップ 3: Watcher を実装する

実際、データを実行するときの Watcher の実装は比較的簡単です。実行される操作

class Watcher {
 constructor(vm, cb) {
  this.cb = cb
  this.vm = vm
 }
 update(){
  this.run()
 }
 run(){
  this.cb.call(this.vm)
 } 
}
ログイン後にコピー

ステップ 4: タッチして依存関係を取得します

上記の 3 つのステップで、データの変更が更新をトリガーする可能性があることがわかりました。ここでの問題は、ウォッチャーを接続できないことです。データ。

データの属性がdefineReactiveに設定された後、データの値を変更するとセットがトリガーされることがわかっています。次に、データの上限値を取得すると、get がトリガーされます。したがって、これを利用して、最初に次のレンダリング関数を実行して、ビューの更新をサポートするために必要なデータを把握し、それをデータのサブスクライバーとして記録できます。

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()
  }
 })
}
ログイン後にコピー

最後に、プロキシを使用してデータ アクセスを vue オブジェクトにバインドする方法を見てみましょう

 _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))
ログイン後にコピー

以下はインスタンス全体の完全なコードです

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

 
  

ログイン後にコピー

上記は、vue データ全体の概念全体です。駆動部分。実装についてさらに詳しく知りたい場合は、vue コードのこの部分を詳しく調べることをお勧めします。

上記は私があなたのためにまとめたものです。

関連記事:

vue+element-ui+ajaxを使ってテーブルのインスタンスを実装する

live-serverを使ってローカルサーバーを構築して自動更新する方法、具体的な方法とは?

下位バージョンのブラウザがes6のインポートをサポートしていない問題を解決

以上がvue2.0 の応答性を実装する方法 (詳細なチュートリアル)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!