Vue 3 组合式API

简介

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

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

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

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

示例

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

image.png

逻辑功能:

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

实现

<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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,809评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,189评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,290评论 0 359
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,399评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,425评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,116评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,710评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,629评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,155评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,261评论 3 339
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,399评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,068评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,758评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,252评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,381评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,747评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,402评论 2 358

推荐阅读更多精彩内容