10x0 精读Vue官方文档 - 示例 - computed 应用

363 阅读2分钟

精读 Vue 官方文档系列 🎉


使用 Computed 进行值的转换。

  • 非异步的基于数据变更监听来进行值的转换完全可以使用 computed 来代替 watch
  • 如果转换的值会被多个地方使用到,更应该使用计算属性,因为计算属性具有缓存的特性。
  • 如果不需要缓存,则可以考虑直接在模板中使用方法进行转换,因为响应式数据的变更必定会触发模板的重新渲染,然后方法便可以被重新执行。
<template>
  <div>
    <p><input type="text" v-model="str" /></p>
    <p>
      <b>{{ btoa }}</b>
    </p>
    <p>repeated:{{ btoa }}</p>
  </div>
</template>
<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      str: "hello world!",
    };
  },
  computed: {
    btoa() {
      return window.btoa(this.str);
    },
  },
};
</script>

因为模板中无法访问 window 对象,所以需要借助计算属性调用 window.btoa 方法,如果你是用的外部导入的方法,那么在转换数据无需多次使用的情况下,可以更加的精简代码:

<template>
  <div>
    <p><input type="text" v-model="str" /></p>
    <p>
      <b>{{ changeStr(str) }}</b>
    </p>
  </div>
</template>
<script>
import {myBtoA} from './myBtoA.js';
import {ref} from '@vue/composition-api';
export default defineComponent({
  name: "UseComputed",
  setup(){
    const {value:str, changeStr:change} = myBtoA();
    return {
       str,
       changeStr
    }
  });
};
</script>

其实最常见的需求场景应该属接收组件外的 props 然后转换为组件内的 data

<script>
export default defineComponent({
   name:"UseComputed",
   props:["propData"],
   setup(props){
      const data = computed(()=>props.propData);
      return {data};
   }
})
</script>

当然,实现的方式有很多,例如 watch 监听命令式执行转换,或者是基于事件回调,但都没有 computed 的那么优雅。

扩展一下,如果此时需要为数据的变更增加防抖呢?解决的办法:

  1. v-model 拆分为 value 与 input 两个,然后专门为 input 事件应用 debounce 方法,来防抖的进行数据变更。
  2. 自定义指令,劫持 input 事件进行防抖。
  3. 使用 v-model.lazy 进行一定小幅度的优化。

使用 computed 进行条件过滤。

{
 computed: {
    filterData() {
      let dataSource = this.dataSource;
      let searchFilter = this.searchFilter;
      let sortKey = this.sortKey;

      if (searchFilter) {
        dataSource = dataSource.filter((record) => {
          return Object.keys(record).some((key) => {
            return String(record[key]).toLowerCase().indexOf(searchFilter) > -1;
          });
        });
      }

      if (sortFiter) {
        dataSource = dataSource.sort((a, b) => {
          const first = a[sortKey];
          const last = b[sortKey];
          return a === b ? 0 : a > b ? 1 : -1;
        });
      }

      return dataSource;
    },
  },}

如果你的数据源受多种响应式条件影响,那么将它们放在一个 computed 中进行处理,将是一个非常适合的方式。

watchcomputed 结合

我们总是强调,computed 用在一个数据受多个数据影响的场景,而 watch 则用在一个数据的变更会影响多个数据的情况,但实际上,二者可以结合使用,将 computed 作为 watch 的监听数据,可以将它们的优势发挥到极致。

<template>
  <div>
    <input type="text" v-model="value1" />
    <input type="radio" value="a" v-model="value2" /><input type="radio" value="b" v-model="value2" />
    <hr/>
    <button @click="download">download</button>
  </div>
</template>
<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      value1: "",
      value2: "a",
    };
  },
  computed: {
    filter() {
      const { value1, value2 } = this;
      return { value1, value2 };
    },
  },
  methods: {
    download() {
      console.log("download", this.filter);
    },
    getData() {
      console.log("fetch data", this.filter);
    },
  },
  created() {
    this.$watch("filter", this.getData, { immediate: true });
  },
};
</script>