首頁  >  文章  >  web前端  >  用Vue.js實現監聽屬性的變化

用Vue.js實現監聽屬性的變化

高洛峰
高洛峰原創
2016-12-06 15:29:461285瀏覽

前言

建立 Vue 實例時,Vue 將遍歷 data 的屬性,透過 ES5 的 Object.defineProperty 將它們轉為 getter/setter,在其內部 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

   


當屬性變化後,響應函數將會被調用,在其內部,this 自動綁定到 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 ,在同一事件循環內,多次資料變更將會被快取起來,在下次事件循環中,Vue 刷新佇列並僅執行必要的更新。

如下:

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* 中,將Model 層資料展現到View,經常有複雜的資料處理邏輯,明智。

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²"

   


在計算屬性內部,this 自動綁定 vm,因此聲明計算屬性時需要避免使用箭頭函數。

上例中,vm.width 和 vm.height 是回應的,vm.area 內部首次讀取 this.width 和 this.height 時,Vue 收集其做為 vm.area 的依賴,此後 vm.width vm. vm.height變化時,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 GitHub 位址:https://github.com/cnlon/ob.js

安裝

npm install --save ob.js

   


const target = {a: 1}
ob(target, 'a', function (newValue, oldValue) {
 console.log(newValue, oldValue) // 3 1
})
target.a = 3

   


像聲明Vue 實例一樣傳入參數集合

const target = {a: 1}
ob.compute(target, 'b', function () {
 return this.a * 2
})
target.a = 10
console.log(target.b) // 20

   


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn