応答システムは Vue の重要な機能であり、プロパティを変更するとビューを更新できるため、状態管理が非常にシンプルかつ直感的になります。
Vue インスタンスを作成するとき、Vue はデータのプロパティを走査し、ES5 の Object.defineProperty を通じてそれらをゲッター/セッターに変換します。内部的には、Vue は依存関係を追跡し、変更を通知できます。
const vm = new Vue({ data: {foo: 1} // 'vm.foo' (在内部,同 'this.foo') 是响应的 })
プロパティの変更を監視する
Vue のインスタンスは、プロパティの変更を監視するための $watch メソッドを提供します。
const vm = new Vue({ data: {foo: 1} }) vm.$watch('foo', function (newValue, oldValue) { console.log(newValue, oldValue) // 输出 2 1 console.log(this.foo) // 输出 2 }) vm.foo = 2
プロパティが変更されると、応答関数が呼び出され、内部的には自動的に Vue インスタンス vm にバインドされます。
応答は非同期であることに注意してください。以下の通り:
const vm = new Vue({ data: {foo: 1} }) vm.$watch('foo', function (newValue, oldValue) { console.log('inner:', newValue) // 后输出 "inner" 2 }) vm.foo = 2 console.log('outer:', vm.foo) // 先输出 "outer" 2
は $watch Vue を通じてデータとビューのバインディングを実現します。データ変更が検出されると、Vue は同じイベント ループ内で DOM を非同期的に更新し、次のイベント ループでキューを更新し、必要な更新のみを実行します。以下の通り:
const vm = new Vue({ data: {foo: 1} }) vm.$watch('foo', function (newValue, oldValue) { console.log('inner:', newValue) // 后只输出一次 "inner" 5 }) vm.foo = 2 vm.foo = 3 vm.foo = 4 console.log('outer:', vm.foo) // 先输出 "outer" 4 vm.foo = 5
計算されたプロパティ
MV* モデルレイヤーデータをビューに表示する場合、多くの場合、複雑なデータ処理ロジックが存在します。この場合、計算されたプロパティを使用する方が賢明です。
const vm = new Vue({ data: { width: 0, height: 0, }, computed: { area () { let output = '' if (this.width > 0 && this.height > 0) { const area = this.width * this.height output = area.toFixed(2) + 'm²' } return output } } }) vm.width = 2.34 vm.height = 5.67 console.log(vm.area) // 输出 "13.27m²"
計算プロパティ内では、これは自動的に vm にバインドされるため、計算プロパティを宣言するときにアロー関数の使用を避ける必要があります。
上記の例では、vm.width と vm.height が応答します。vm.area が初めて this.width と this.height を読み取るとき、Vue はそれらを vm.area の依存関係として収集します。 vm.高さが変更されると、vm.area が再評価されます。
計算されたプロパティは、その依存関係キャッシュに基づいています。vm.width と vm.height が変更されない場合、vm.area を複数回読み取ると、再評価することなく、前の計算結果がすぐに返されます。
同様に、vm.width と vm.height は応答性があるため、依存するプロパティを vm.area の変数に割り当て、変数を読み取ることで、プロパティを読み取る回数を減らすことができます。同時に、Vue は条件付き分岐でプロパティを読み取ります。依存関係を収集できない場合があります。
新しい実装は次のとおりです:
const vm = new Vue({ data: { width: 0, height: 0, }, computed: { area () { let output = '' const {width, height} = this if (width > 0 && height > 0) { const area = width * height output = area.toFixed(2) + 'm²' } return output } } }) vm.width = 2.34 vm.height = 5.67 console.log(vm.area) // 输出 "13.27m²"
ob.js を通じて Vue の属性観察モジュールを単独で使用します
学習と使用を容易にするために、ob.js は Vue の属性観察モジュールを抽出してカプセル化します。
インストール
npm install --save ob.js
プロパティの変更を観察
const target = {a: 1} ob(target, 'a', function (newValue, oldValue) { console.log(newValue, oldValue) // 3 1 }) target.a = 3
計算されたプロパティを追加
const target = {a: 1} ob.compute(target, 'b', function () { return this.a * 2 }) target.a = 10 console.log(target.b) // 20
Vueインスタンスを宣言するのと同じようにパラメータセットを渡します
const options = { data: { PI: Math.PI, radius: 1, }, computed: { 'area': function () { return this.PI * this.square(this.radius) }, }, watchers: { 'area': function (newValue, oldValue) { console.log(newValue) // 28.274333882308138 }, }, methods: { square (num) { return num * num }, }, } const target = ob.react(options) target.radius = 3