この記事では主に 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;idefineReactive(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 サイトの他の関連記事を参照してください。