简介
组合式API
,是Vue 3
的新功能,主要是将组件的逻辑关注点,收集在一起,提高逻辑代码的复用率,方便复杂组件逻辑功能的理解与维护。
实现上,通过setup
组件选项,整合逻辑功能,并返回,在组件模板直接使用。setup
与methods
、data
、computed
等是向下兼容的。
需要注意的是: 在setup
中不能使用this
,会找不到组件的实例,因为setup
选项是在组件创建前执行的。methods
、data
、computed
定义的属性、方法均无法在setup
中被获取。
接下来我们通过一个简单的示例来了解组合式API的关注点分离、逻辑功能复用;
示例
示例: 一个计数器,每次遇到偶数的时候,加入列表进行展示;可排序翻转、可修改列表数据。
![](https://img.haomeiwen.com/i1977357/3ebacfff8beb00c9.png)
逻辑功能:
- 基于步幅的累加
- 列表数据更新(添加)
- 列表数据排序&翻转
- 列表数据的修改
实现
<script>export default { ///定义组件属性 props: { initialCount: { type: Number, required: false, default: 0, }, step: { type: Number, default: 1 } }, data() { return { count: this.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: { type: Number, required: false, default: 0, }, step: { type: Number, default: 1, }, }, 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/useIncrementimport {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>
参考资料
https://v3.cn.vuejs.org/guide/composition-api-introduction.html
网友评论