Home  >  Article  >  Web Front-end  >  Use Vue to observe property changes

Use Vue to observe property changes

高洛峰
高洛峰Original
2016-11-22 11:39:131030browse

The response system is a significant feature of Vue. Modifying properties can update the view, which makes state management very simple and intuitive.
When creating a Vue instance, Vue will traverse the properties of data and convert them into getters/setters through ES5's Object.defineProperty. Internally, Vue can track dependencies and notify changes.

const vm = new Vue({
  data: {foo: 1} // 'vm.foo' (在内部,同 'this.foo') 是响应的
})

Observe property changes

Instances of Vue provide the $watch method for observing property changes.

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

When the property changes, the response function will be called, and internally, this is automatically bound to the Vue instance vm.
It should be noted that the response is asynchronous. As follows:

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

realizes the binding of data and views through $watch Vue. When data changes are observed, Vue updates the DOM asynchronously. Within the same event loop, multiple data changes will be cached. In the next event loop, Vue refreshes the queue and only performs necessary updates. As follows:

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

Computed properties

MV* In displaying Model layer data to View, there is often complex data processing logic. In this case, it is more sensible to use computed properties.

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

Inside a computed property, this is automatically bound to vm, so you need to avoid using arrow functions when declaring computed properties.
In the above example, vm.width and vm.height are responsive. When vm.area reads this.width and this.height for the first time, Vue collects them as dependencies of vm.area. After that, vm.width or vm. When height changes, vm.area is re-evaluated.
Computed properties are based on its dependency cache. If vm.width and vm.height do not change, reading vm.area multiple times will immediately return the previous calculation results without having to evaluate again.
Similarly because vm.width and vm.height are responsive, you can assign dependent properties to a variable in vm.area and read the variables to reduce the number of times you read properties. At the same time, in conditional branches, Vue sometimes Unable to collect dependencies.
The new implementation is as follows:

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

Use Vue’s attribute observation module alone through ob.js

To facilitate learning and use, ob.js extracts and encapsulates the attribute observation module in Vue.

Install

npm install --save ob.js

Observe property changes

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

Add computed properties

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

Pass in the parameter set just like declaring a Vue instance

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


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn