VUE entry (4)

And the listener properties calculation

 

Computed Property

The expression in the template is very convenient, but They are primarily designed for simple operation. Putting too much logic in the template template will be too heavy and difficult to maintain. E.g:

<div id="example">
  {{ message.split('').reverse().join('') }}
</div>

In this place, the template is no longer a simple declarative logic. You have to look at some time to realize that here is you want to display variable  message flip string. When you want to refer to flip the string here many times in the template, it will be more difficult to handle.

So, for any complex logic, you should use the calculation attribute .

Examples basis

<div id="example">
  <p>Original message: "{{ message }}"</p>
  <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // 计算属性的 getter
    reversedMessage: function () {
      // `this` 指向 vm 实例
      return this.message.split('').reverse().join('')
    }
  }
})

result

Original message: "Hello"

Computed reversed message: "olleH"

Here we declare a calculated property  reversedMessage. We offer as a function of the property  vm.reversedMessage getter function:

console.log(vm.reversedMessage) // => 'olleH'
vm.message = 'Goodbye'
console.log(vm.reversedMessage) // => 'eybdooG'

You can open the browser console modified example of the vm itself.

vm.reversedMessage The value is always dependent on  vm.message the value.

You can be as binding as common property of binding to calculate properties in the template. Vue know  vm.reversedMessage rely on  vm.message, so when  vm.message change occurs, all dependent  vm.reversedMessage binding will be updated. And best of all is that we have to declaratively create this dependency: calculate the property getter functions are no side effects (side effect), making it easier to test and understand.

 

Calculation method vs property cache

You may have noticed that we can achieve the same effect by calling in an expression method:

<p>Reversed message: "{{ reversedMessage() }}"</p>
// 在组件中
methods: {
  reversedMessage: function () {
    return this.message.split('').reverse().join('')
  }
}

We can define the same function as a method rather than a calculated property. The final results of the two methods is indeed identical. However, the difference is calculated based on their properties are dependent responsive caching . They will only re-evaluated at the time-dependent change of Formula correlation response. This means that as long as  message no change, many visits to  reversedMessagethe calculation results before the property will return immediately to calculate, without having to perform functions again.

This also means that the following calculated property will not be renewed, because  Date.now() not dependent response of formula:

computed: {
  now: function () {
    return Date.now()
  }
}

In contrast, whenever the trigger re-rendering, calling the method will always execute the function once again.

Why do we need to cache? Suppose we have a performance overhead is relatively large computational properties of  A , it needs to traverse a huge array and do a lot of calculations. Then we may have other properties depend on the calculation  A  . If there is no cache, we will inevitably multiple executions  A  getter is! If you do not want to have the cache, instead of using the method.

 

Computed Property vs listeners property

Vue provides a more versatile way to observe changes and the response data on the Vue instance: listener properties . When you have some data with other data needs to change and change, you can easily abused  watch- especially if you previously used AngularJS. Often, however, a better practice is to use the calculation attribute rather than a command-style  watch callback. Come to think of this example:

<div id="demo">{{ fullName }}</div>
var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar',
    fullName: 'Foo Bar'
  },
  watch: {
    firstName: function (val) {
      this.fullName = val + ' ' + this.lastName
    },
    lastName: function (val) {
      this.fullName = this.firstName + ' ' + val
    }
  }
})

The above code is the command type and repetitive. It was compared with the calculated properties version:

var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar'
  },
  computed: {
    fullName: function () {
      return this.firstName + ' ' + this.lastName
    }
  }
})

 

setter calculated properties

The default attribute is calculated only getter, but if necessary you can also provide a setter:

// ...
computed: {
  fullName: {
    // getter
    get: function () {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
      var names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}
// ...

Now run  vm.fullName = 'John Doe' time, setter will be called, vm.firstName and  vm.lastNamewill be updated accordingly.

 

Listener

Although the computing properties more appropriate in most cases, but sometimes requires a custom listener. That's why Vue by  watch providing a more general approach options to respond to changes in the data. When the need to perform asynchronous data change operation or large overhead, this approach is most useful.

E.g:

<div id="watch-example">
  <p>
    Ask a yes/no question:
    <input v-model="question">
  </p>
  <p>{{ answer }}</p>
</div>
<!-- 因为 AJAX 库和通用工具的生态已经相当丰富,Vue 核心代码没有重复 -->
<!-- 提供这些功能以保持精简。这也可以让你自由选择自己更熟悉的工具。 -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
  el: '#watch-example',
  data: {
    question: '',
    answer: 'I cannot give you an answer until you ask a question!'
  },
  watch: {
    // 如果 `question` 发生改变,这个函数就会运行
    question: function (newQuestion, oldQuestion) {
      this.answer = 'Waiting for you to stop typing...'
      this.debouncedGetAnswer()
    }
  },
  created: function () {
    // `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
    // 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率
    // AJAX 请求直到用户输入完毕才会发出。想要了解更多关于
    // `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,
    // 请参考:https://lodash.com/docs#debounce
    this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
  },
  methods: {
    getAnswer: function () {
      if (this.question.indexOf('?') === -1) {
        this.answer = 'Questions usually contain a question mark. ;-)'
        return
      }
      this.answer = 'Thinking...'
      var vm = this
      axios.get('https://yesno.wtf/api')
        .then(function (response) {
          vm.answer = _.capitalize(response.data.answer)
        })
        .catch(function (error) {
          vm.answer = 'Error! Could not reach the API. ' + error
        })
    }
  }
})
</script>

In this example, use the  watch option allows us to perform asynchronous operations (the API to access a), we perform the operation frequency limit and before we get the final result, an intermediate state. These are computed attribute can not be done.

In addition  watch to the options, you can also use the command-style  vm. $ Watch API .

 

 

 

 

 

 

Guess you like

Origin blog.csdn.net/qq_42488433/article/details/94719480