vue computed属性真的那么好用吗?

241 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

computed是什么不用说了吧,大家都会用computed属性,这么好用的computed属性有啥问题呢?

    
<template>
  <div class="hello">
    <div style="padding: 20px;width: 300px;margin: auto;">
      {{userName}}
    </div>

  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  components: {

  },

  props: {
    msg: String
  },
  computed:{
    userName(){
      return this.user.name+'bbb';
    }
  },

  data() {
    return {
      user:{
        name:'11',
      },
    }
  },

}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

这是一个最简单的计算属性用法,给user.name 添加了一个后缀

image.png

会出现一个什么问题呢?

<template>
  <div class="hello">
    <div style="padding: 20px;width: 300px;margin: auto;">
      {{userName}}
      <div>
        {{user}}
      </div>
      <div>
        <a-input v-model="user.pass" />
      </div>
    </div>

  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  components: {

  },

  props: {
    msg: String
  },
  computed:{
    userName(){
      console.log('computed userName 执行了');
      return this.user.name+'bbb';
    }
  },

  data() {
    return {
      user:{
        name:'11',
      },
     }
  },

  methods:{

  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

这里增加了一个输入框,使用v-model 增加了一个字段,可以看到computed userName 执行了2次,computed属性的问题就出来了,它是深度监听的,字段的属性添加等都会造成计算属性重新计算,所谓的缓存其实是依赖的字段不能有任何的改变

image.png

image.png

那怎么解决呢?

这里我们改成watch,只监听name字段

watch:{
    'user.name':{}
}
<template>
  <div class="hello">
    <div style="padding: 20px;width: 300px;margin: auto;">
      {{userName}}
      <div>
        {{user}}
      </div>
      <div>
        <a-input v-model="user.pass" />
      </div>
    </div>

  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  components: {

  },

  props: {
    msg: String
  },
  computed:{
    userName(){
      console.log('computed userName 执行了');
      return this.user.name+'bbb';
    }
  },
  watch:{

    'user.name':{//只监听 user.name字段
      immediate:true,
      handler(){
        console.log('watch userName 执行了');
        this.userName1 = this.user.name+'bbb';

      }
    }
  },
  data() {
    return {
      user:{
        name:'11',
      },
     }
  },

  methods:{

  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

image.png

可以看到watch只执行了一次,减少了计算

这里还有一个注意就是watch的deep属性也是一样的,如果你知道你只依赖对象的一个子字段,那么最好只监听一个字段,避免很多计算,特别是watch里面有可能有api的调用,会造成很多不必要的请求