likes
comments
collection
share

Vue 3 组合式API

作者站长头像
站长
· 阅读数 45

简介

组合式API,是Vue 3的新功能,主要是将组件的逻辑关注点,收集在一起,提高逻辑代码的复用率,方便复杂组件逻辑功能的理解与维护。

实现上,通过setup组件选项,整合逻辑功能,并返回,在组件模板直接使用。setupmethodsdatacomputed等是向下兼容的。

需要注意的是: 在setup中不能使用this,会找不到组件的实例,因为setup选项是在组件创建前执行的。methodsdatacomputed定义的属性、方法均无法在setup中被获取。

接下来我们通过一个简单的示例来了解组合式API的关注点分离、逻辑功能复用;

示例

示例:  一个计数器,每次遇到偶数的时候,加入列表进行展示;可排序翻转、可修改列表数据。

Vue 3 组合式API逻辑功能:

  1. 基于步幅的累加
  2. 列表数据更新(添加)
  3. 列表数据排序&翻转
  4. 列表数据的修改

实现

<script>
export default {
    ///定义组件属性
   props: {
    initialCount: {
      typeNumber,
      requiredfalse,
      default0,
    },
    step: {
        typeNumber,
        default1
    }
  },

  data() {
    return {
     countthis.initialCount,//功能1
     stepValue : this.step,//功能1
     captureValues: [],//功能2、3、4
    };
  },
  methods: {
    increment() {//功能1
      this.count += this.stepValue;
    },
    sortCaptureValues() {//功能2
      this.captureValues.sort((a, b) => a > b).reverse();
    },
    updateCaptureValues() {//功能3
      if (this.isEven) {
        this.captureValues.push(this.count);
      }
    },
    changeCaptureValues() {//功能4
      this.captureValues = this.captureValues.map((a) => a * 10);
    },
  },
  computed: {
    isEven() {//功能3
      return this.count % 2 == 0;
    },
  },
  watch: {
    count(newVal, oldVal) {
     this.updateCaptureValues();//功能3
    },
  },
  onmounted() {
    console.log("🔥");
  },
};
</script>

可以看到组件中功能实现是分散在不同的组件选项中,当功能很多很复杂的时候,代码的可读性也会大大降低。多个组件间,相同逻辑功能复用不易。 Vue 2 中,虽然可通过mixins解决,但mixins容易出现命名冲突等问题。

setup 实现

接下来,我们基于组合式API来实现,代码如下:

<script>
import { ref, computed, watch } from "vue";
export default {
  ///定义组件属性
  props: {
    initialCount: {
      typeNumber,
      requiredfalse,
      default0,
    },
    step: {
      typeNumber,
      default1,
    },
  },
  setup(props) {
    ///功能1:基于步幅的累加
    const count = ref(props.initialCount);
    const stepValue = ref(props.step);
    const increment = () => (count.value += stepValue.value);

    ///功能2: 列表数据更新(添加)
    const captureValues = ref([]);
    const isEven = computed(() => count.value % 2 === 0);
    const updateCaptureValues = () => {
      console.log(isEven);
      if (isEven.value === true) {
        captureValues.value.push(count.value);
      }
    };
    ///功能3: 列表数据排序&翻转
    const sortCaptureValues = () => {
      captureValues.value.sort((a, b) => a > b).reverse();
    };

    ///功能4:列表数据的修改
    const changeCaptureValues = () => {
      captureValues.value = captureValues.value.map((a) => a * 10);
    };

    ///监听count
    watch(count, updateCaptureValues);

    return {
      count,
      stepValue,
      increment,
      isEven,
      captureValues,
      updateCaptureValues,
      sortCaptureValues,
      changeCaptureValues,
    };
  },
};
</script>

可以清楚的看到代码逻辑功能更加聚焦,可读性增强。 需要注意的是,组件中的数据需要通过ref变为响应式的。

功能复用

基于setup的实现方式,我们可将功能提取到独立的js文件中,以便其他组件复用。

///文件路径: src/composables/useIncrement
import {ref,computed} from 'vue'
///功能1:基于步幅的累加
export default function useIncrement(initialCount,step) {
    const count = ref(initialCount)
    const stepValue = ref(step)
    const increment = () => count.value += stepValue.value
    return {
        count,
        stepValue,
        increment
    }
}
 ///功能2: 列表数据更新(添加)
export function useUpdateValues(count) {
    const captureValues = ref([]);
    const isEven = computed(() => count.value % 2 === 0);
    const updateCaptureValues = () => {
      if (isEven.value === true) {
        captureValues.value.push(count.value);
      }
    };
    return {
        captureValues,
        updateCaptureValues,
    }
}
///功能3: 列表数据排序&翻转
export function useSortValues(values) {
    const sortCaptureValues = () => {
        values.value.sort((a, b) => a > b).reverse();
    };
    return { sortCaptureValues }
}
///功能4:列表数据的修改
export function useChangeValues(values,base) { 
    const changeCaptureValues = () => {
        values.value = values.value.map((a) => a * base);
      };
      return {
        changeCaptureValues
      }
}

再将提取的功能函数引入到我们Counter组件中:

<script>
import {watch,onMounted} from "vue";
import useIncrement, {useUpdateValues,useSortValues,useChangeValues} from "../composables/useIncrement";
export default {
  ///定义组件属性
  props/*...*/
  
  setup(props) {
    ///累加
    const {count, stepValue, increment} = useIncrement(props.initialCount, props.step)
    ///添加到列表
    const {captureValues,updateCaptureValues} = useUpdateValues(count)
    ///排序数据
    const {sortCaptureValues} = useSortValues(captureValues)
    ///改变数据
    const { changeCaptureValues } = useChangeValues(captureValues,10)
    ///监听count
    watch(count, updateCaptureValues);
    ///生命周期
    onMounted(()=>console.log("已挂载组件"))
    return {
      count,
      stepValue,
      increment,
      captureValues,
      updateCaptureValues,
      sortCaptureValues,
      changeCaptureValues,
    };
  },
};
</script>

这样其他的组件就可以复用提取功能了,比如:SimpleCounter组件复用基于步幅的累加功能。

<template>
    <button @click="increment" > {{count}}</button>
</template>

<script>
import useIncrement from "../composables/useIncrement";
export default {
    setup(props) {
        return {
            ...useIncrement(0,2// 增幅为2,初始值为0,的计数器
        }
    }
}
</script>

或者使用<script setup>单文件组件中使用组合式API的语法糖:

<template>
    <button @click="increment" > {{count}}</button>
</template>

<script setup>
import useIncrement from "../composables/useIncrement";
const {count, increment} = useIncrement(0,2// 增幅为2 ,初始值为0,的计数器
</script>

参考资料

v3.cn.vuejs.org/guide/compo…

本文使用 markdown.com.cn 排版