用 Vue 來觀察屬性變化

響應系統是 Vue 一個顯著功能,修改屬性,能夠更新視圖,這讓狀態管理變得很是簡單且直觀。
建立 Vue 實例時,Vue 將遍歷 data 的屬性,經過 ES5 的 Object.defineProperty 將它們轉爲 getter/setter,在其內部 Vue 能夠追蹤依賴、通知變化。javascript

const vm = new Vue({
  data: {foo: 1} // 'vm.foo' (在內部,同 'this.foo') 是響應的
})

觀察屬性變化

Vue 的實例提供了 $watch 方法,用於觀察屬性變化。java

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 上。
須要注意的是,響應是異步的。以下:react

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 刷新隊列並僅執行必要的更新。以下:git

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,常常有複雜的數據處理邏輯,這種狀況下,使用計算屬性 (computed property) 更加明智。github

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.widthvm.height 是響應的,vm.area 內部首次讀取 this.widththis.height 時,Vue 收集其作爲 vm.area 的依賴,此後 vm.widthvm.height 變化時,vm.area 從新求值。
計算屬性是基於它的依賴緩存,若是 vm.widthvm.height 沒有變化,屢次讀取 vm.area,會當即返回以前的計算結果,而沒必要再次求值。
一樣因爲 vm.widthvm.height 是響應的,在 vm.area 中能夠將依賴的屬性賦值給一個變量,經過讀取變量來減小讀取屬性次數,同時解決在條件分支中,Vue 有時會沒法收集到依賴的問題
新的實現以下:npm

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 smart-observe 單獨使用 Vue 的屬性觀察模塊

爲方便學習和使用,smart-observe 將 Vue 中屬性觀察模塊提取並封裝了一下。緩存

smart-observe GitHub 地址:https://github.com/cnlon/smar...bash

安裝異步

npm install --save smart-observe

觀察屬性變化函數

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

添加計算屬性

const target = {a: 1}
observe.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 = observe.react(options)
target.radius = 3

更詳細的使用介紹請 點擊這裏

同時推薦其它兩款同類庫

相關文章
相關標籤/搜索