计算属性computed和侦听器watch

淡淡的烟草味﹌ 2022-03-25 02:59 405阅读 0赞
  • 计算属性和侦听器
  • 计算属性

个人理解:

  • computed用来监控自己定义的变量,该变量不在data里面声明,直接在computed里面定义,然后就可以在页面上进行双向数据绑定展示出结果或者用作其他处理,同时绑定的数据必须是响应式依赖;
  • computed比较适合对多个变量或者对象进行处理后返回一个结果值,也就是数多个变量中的某一个值发生了变化则我们监控的这个值也就会发生变化,如购物车;

对于任何复杂逻辑,应当使用计算属性

  1. <template>
  2. <div id="example">
  3. <p>Original message: "{
  4. { message }}"</p>
  5. <p>Computed reversed message: "{
  6. { reversedMessage }}"</p>
  7. </div>
  8. </template>
  9. <script>
  10. export default {
  11. data() {
  12. return{
  13. message: 'Hello'
  14. }
  15. },
  16. computed: {
  17. reversedMessage: function () {// 计算属性的 getter
  18. return this.message.split('').reverse().join('')//this指向当前实例
  19. }
  20. }
  21. }
  22. </script>

this.reversedMessage 的值始终取决于 this.message 的值。最妙的是我们已经以声明的方式创建了这种依赖关系:计算属性的 getter 函数是没有副作用 (side effect) 的,这使它更易于测试和理解。

  • 计算属性缓存 vs 方法

在methods中定义方法也可以实现当前要求:

  1. <template>
  2. <div id="example">
  3. <p>Reversed message: "{
  4. { reversedMessage() }}"</p>
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. data() {
  10. return{
  11. message: 'Hello'
  12. }
  13. },
  14. methods: {
  15. reversedMessage: function () {
  16. return this.message.split('').reverse().join('')
  17. }
  18. }
  19. }
  20. </script>

两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的依赖进行缓存的。只在相关依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。

所以下面代码显示时间将不会更新

  1. computed: {
  2. now: function () {
  3. return Date.now()
  4. }
  5. }

相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。而计算属性取决于响应式依赖,

  • 计算属性 vs 侦听属性

Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性

  • 计算属性的 setter

计算属性默认只有 getter ,不过在需要时你也可以提供一个 setter :

  1. computed: {
  2. fullName: {
  3. // getter
  4. get: function () {
  5. return this.firstName + ' ' + this.lastName
  6. },
  7. // setter
  8. set: function (newValue) {
  9. var names = newValue.split(' ')
  10. this.firstName = names[0]
  11. this.lastName = names[names.length - 1]
  12. }
  13. }
  14. }

侦听器

现在再运行 vm.fullName = 'John Doe' 时,setter 会被调用,vm.firstNamevm.lastName 也会相应地被更新。

虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

例如:

  1. <div id="watch-example">
  2. <p>
  3. Ask a yes/no question:
  4. <input v-model="question">
  5. </p>
  6. <p>{
  7. { answer }}</p>
  8. </div>
  9. <script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
  10. <script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
  11. <script>
  12. var watchExampleVM = new Vue({
  13. el: '#watch-example',
  14. data: {
  15. question: '',
  16. answer: 'I cannot give you an answer until you ask a question!'
  17. },
  18. watch: {
  19. // 如果 `question` 发生改变,这个函数就会运行
  20. question: function (newQuestion, oldQuestion) {
  21. this.answer = 'Waiting for you to stop typing...'
  22. this.debouncedGetAnswer()
  23. }
  24. },
  25. created: function () {
  26. // `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
  27. this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
  28. },
  29. methods: {
  30. getAnswer: function () {
  31. if (this.question.indexOf('?') === -1) {
  32. this.answer = 'Questions usually contain a question mark. ;-)'
  33. return
  34. }
  35. this.answer = 'Thinking...'
  36. var vm = this
  37. axios.get('https://yesno.wtf/api')
  38. .then(function (response) {
  39. vm.answer = _.capitalize(response.data.answer)
  40. })
  41. .catch(function (error) {
  42. vm.answer = 'Error! Could not reach the API. ' + error
  43. })
  44. }
  45. }
  46. })
  47. </script>

结果:

Ask a yes/no question:

I cannot give you an answer until you ask a question!

在这个示例中,使用 watch 选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

发表评论

表情:
评论列表 (有 0 条评论,405人围观)

还没有评论,来说两句吧...

相关阅读