computed 和 watch以及methods

computed 和 watch 的区别和运用的场景?

  • computed: (监测的是 依赖值 )是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;
  • watch: (监测的是 属性值 )更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;

运用场景:
• 当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算;
• 当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

computed的原理?
computed 本质是一个惰性求值的观察者。
computed 内部实现了一个惰性的 watcher,也就是 computed watcher,computed watcher 不会立刻求值,同时持有一个 dep 实例。
其内部通过 this.dirty 属性标记计算属性是否需要重新求值。
当 computed 的依赖状态发生改变时,就会通知这个惰性的 watcher,
computed watcher 通过 this.dep.subs.length 判断有没有订阅者,
有的话,会重新计算,然后对比新旧值,如果变化了,会重新渲染。 (Vue 想确保不仅仅是计算属性依赖的值发生变化,而是当计算属性最终计算的值发生变化时才会触发渲染 watcher 重新渲染,本质上是一种优化。)
没有的话,仅仅把 this.dirty = true。 (当计算属性依赖于其他数据时,属性并不会立即重新计算,只有之后其他地方需要读取属性的时候,它才会真正计算,即具备 lazy(懒计算)特性。)

下面用Computed和Methods实现同一个功能:##

<!-- 计算属性示例 -->
<p>Computed reversed message: "{{ reversedMessage }}"</p>
<script>
  const vm = new Vue({
      el: '#app',
      data: {
          message: 'ABCDEF'
      },
      computed: {
          reversedMessage: function () {
            return this.message.split('').reverse().join('');
          }
      }
})
</script>

<!-- ===================================================== -->

<!-- 方法示例 -->
<p>Reversed message: "{{ reversedMessage() }}"</p>
<script>
  const vm = new Vue({
      el: '#app',
      data: {
          message: 'ABCDEF'
      },
      methods: {
          reversedMessage: function () {
                return this.message.split('').reverse().join('');
          }
      }
  })
</script>

computed 和 methods的区别

  • 计算属性computed的亮点在于:它能够依赖缓存,当计算属性所依赖的数据发生改变时,才会重新触发计算属性方法执行,所以对于较复杂或消耗效率的计算,一定要采用计算属性##

  • 使用methods的方法,每次页面刷新都会触发方法的执行
    而使用计算属性,只要依赖的数据没有变化,就会直接从缓存中读取结果,不需要重新计算,这种做法可以提升效率更可以带来更好的用户体验

  • 使用methods方法可以接受外部传参,使用更加灵活

但是,并不是使用computed就一定更好

computed: {
    now: function(){
        return Data.now();
    }
} 
由于Data.now并不是响应式依赖,所以计算属性now不会更新
但是methods不同,只要重新渲染就会执行   

所以,使用methods还是计算属性主要取决于是否需要缓存
当对大数组遍历或计算量较大时,应使用计算属性,不需要缓存使用methods
具体分析如下:

  1. 可以像绑定普通属性一样在模板中绑定计算属性
  2. 计算属性基于自己的依赖进行缓存, 也就是说,计算属性只有在它的相关依赖发生改变时才会重新求值。这就意味着,上述案例中,只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
  3. 对应的, 每次出发重新渲染时,调用方法总会再次执行函数
  4. 假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A 。如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用方法来替代。

Watch

侦听属性是一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。

当你有一些数据需要随着其它数据变动而变动时,或者当需要在数据变化时执行异步或开销较大的操作时,你可以使用 watch。

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

<div id="watch-example">
  <p>
    Ask a yes/no question:
    <input v-model="question">
  </p>
  <p>{{ answer }}</p>
</div>
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 () {
    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
        })
    }
  }
})

总结

  • watch适合处理的场景是,侦听一个数的变化,当该数据变化,来处理其他与之相关数据的变化(该数据影响别的多个数据)
  • computed适合处理的场景是,获得一个值或者结果,该结果受其他的依赖的影响。(一个数据受多个数据影响)
  • methods用的是也是最多的,一般的事件绑定,普通函数,请求数据方法都是在methods中处理。然后vue的生命周期函数就是在相应的或者合适的时机调用这些定义好的函数。
posted @ 2020-08-10 14:10  Daeeman  阅读(174)  评论(0)    收藏  举报