简言

今天来学习下vue3组合式函数用法,先甩官方链接:组合式函数
vue2的时候,以一个vue文件是按照vue给的模块文件来写的,也就是选项式API写法(一个文件里有template、script、style)。现在vue3新出了一个组合式API写法(一个文件里有template、script、style)。两者区别主要在script部分,选项式API写法中,script是已经预设了属性方法使用方式的,例data、components、computer、watch、methods等;组合式API写法则没有预设(根据暴露的方法或属性按照自己的想法写)。
组合式API的出现弥补了选项式API的一些缺点:

  • 代码不易理解阅读,因为他是属性和方法分开来写,看代码得跳来跳去的看。
  • 代码逻辑不清晰难以维护,一旦文件代码变多,不是原作者的人看得直接头大。
  • js代码复用低,相似的代码需要cv,或者使用mixin、extends。

现在好了,可以用组合式函数了,很nice,我们下面来使用下。

使用

使用方式

  • 文件中使用单独的script片段使用,lang需要指定setup。
<script lang="ts" setup>
</script>
  • 在选项式写法中新增一个setup方法使用,需要返回要使用的属性方法。
<script>
export default {
	setup(){
		return {}
	}
	...
}
</script>

组合式API

使用之前我们先来熟悉下vue为组合式写法提供的方法或属性,官方API链接。api有点多,我们先只了解常用的几个:

  • ref() - 接受一个内部值,返回一个响应式的、可更改的 ref 对象,此对象只有一个指向其内部值的属性 .value。
  • computed() - 接受一个 getter 函数,返回一个只读的响应式 ref 对象。该 ref 通过 .value 暴露 getter 函数的返回值。它也可以接受一个带有 get 和 set 函数的对象来创建一个可写的 ref 对象。
  • reactive() - 返回一个对象的响应式代理。
  • watchEffect() - 立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行。相当于监听器,他会首先执行一次。
  • watch() - 侦听一个或多个响应式数据源,并在数据源变化时调用所给的回调函数。
  • onMounted() - 注册一个回调函数,在组件挂载完成后执行。
  • onBeforeMount() - 注册一个钩子,在组件被挂载之前被调用。
  • onBeforeUnmount() - 注册一个钩子,在组件实例被卸载之前调用。

常用的就这几个,上面两种方式使用组合式API会有所不同,建议看下官网了解下。

基本使用

我在一个页面内使用了以前创建的几个组件,然后使用组合式函数分割js代码:
首先创建一个承载数据函数的文件夹,这个文件夹想放哪就放哪,取名也是。这里因为基本都是数据,所以我在同级创建了一个data文件夹,里面存放管理数据的ts文件:
示例
编写ts文件,建议一个ts文件只放一个组合式函数并默认导出,组合式函数约定用驼峰命名法命名,并以“use”作为开头。
attribute.ts

/*
 * @Date: 2022-11-16 11:07:43
 * @LastEditors: zhangsk
 * @LastEditTime: 2022-11-16 11:08:28
 * @FilePath: \basic-demo\src\pages\data\attribute.ts
 * @Label: Do not edit
 */

export default function useAttributeData() {
  const attributes = {
    style: "backgroundColor:#eaeaea;",
    class: "bind",
    hhh: "lalala",
  };
  return {
    attributes
  }
}

calculate.ts

/*
 * @Date: 2022-11-16 10:58:28
 * @LastEditors: zhangsk
 * @LastEditTime: 2022-11-16 11:03:54
 * @FilePath: \basic-demo\src\pages\data\calculate.ts
 * @Label: Do not edit
 */

import { reactive, ref } from "vue";

export default function useCalculateData() {
  const form2 = reactive({
    valueOne: 0,
    selected: "+",
    valueTwo: 0,
  });
  const result = ref(0);
  //  计算
  const calculateFun = () => {
    const { selected, valueOne, valueTwo } = form2;
    switch (selected) {
      case "+":
        result.value = valueOne * 1 + valueTwo * 1;
        break;
      case "-":
        result.value = valueOne - valueTwo;
        break;
      case "*":
        result.value = valueOne * valueTwo;
        break;
      case "/":
        result.value = valueOne / valueTwo;
    }
  };
  //  返回需要的属性和方法
  return {
    form2,
    result,
    calculateFun
  }
}

dynamic.ts

import { reactive, ref, watch } from "vue";

export default function useDynamicData() {
  interface component {
    name: string; //  组件名
    attrs: object; //组件属性
    key: string;
    listenEvents?: object; //  监听事件名
    content?: any; //  组件内容
  }
  const value = ref("1");
  interface stringKey {
    [key: string]: any;
  }
  interface obj extends stringKey {
    inputValue: string;
    checkedNames: Array<string>;
  }
  const form = reactive({
    inputValue: "",
    checkedNames: [],
  }) as any;
  const componentsArr: Array<component> = [
    {
      name: "input",
      key: "inputValue",
      attrs: {
        type: "text",
        placeholder: "请输入值",
        "v-model": form.inputValue,
      },
      listenEvents: {
        input: (e: any) => {
          value.value = e.target.value;
          form.inputValue = e.target.value;
        },
      },
    },
    {
      name: "input",
      key: "checkedNames",
      attrs: {
        type: "checkbox",
        value: "one",
        id: "one",
        "v-model": form.checkedNames,
      },
      listenEvents: {
        change: (e: any) => {
          CheckboxChange(e.target.value);
        },
      },
      content: {
        name: "label",
        attrs: {
          for: "one",
        },
        content: "one",
      },
    },

    {
      name: "input",
      key: "checkedNames",

      attrs: {
        type: "checkbox",
        value: "two",
        id: "two",
        "v-model": form.checkedNames,
      },
      listenEvents: {
        change: (e: any) => {
          CheckboxChange(e.target.value);
        },
      },
      content: {
        name: "label",
        attrs: {
          for: "two",
        },
        content: "two",
      },
    },

    {
      name: "input",
      key: "checkedNames",
      attrs: {
        type: "checkbox",
        value: "three",
        id: "three",
        "v-model": form.checkedNames,
      },
      listenEvents: {
        change: (e: any) => {
          CheckboxChange(e.target.value);
        },
      },
      content: {
        name: "label",
        attrs: {
          for: "three",
        },
        content: "three",
      },
    },
  ];
  watch(
    () => value.value,
    () => {
      console.log(value.value, "value改变");
    }
  );
  const CheckboxChange = (v: string) => {
    if (form.checkedNames.includes(v)) {
      form.checkedNames = form.checkedNames.filter((v2: string) => v2 !== v);
    } else {
      form.checkedNames.push(v);
    }
  };
  return {
    form,
    value,
    componentsArr
  }
}

tree.ts

/*
 * @Date: 2022-11-16 11:04:58
 * @LastEditors: zhangsk
 * @LastEditTime: 2022-11-16 11:05:25
 * @FilePath: \basic-demo\src\pages\data\tree.ts
 * @Label: Do not edit
 */

import { reactive } from "vue";

export default function useTreeData() {
  const treeData = reactive([
    {
      name: "1-1",
      key: "1-1",
      lable: "1-1",
      children: [
        {
          name: "1-1-1",
          key: "1-1-1",
          lable: "1-1-1",
          children: [],
        },
        {
          name: "1-1-2",
          key: "1-1-2",
          lable: "1-1-2",
          children: [],
        },
        {
          name: "1-1-3",
          key: "1-1-3",
          lable: "1-1-3",
          children: [],
        },
      ],
    },
    {
      name: "1-2",
      key: "1-2",
      lable: "1-2",
      children: [
        {
          name: "1-2-1",
          key: "1-2-1",
          lable: "1-2-1",
          children: [
            {
              name: "1-2-1-1",
              key: "1-2-1-1",
              lable: "1-2-1-1",
              children: null,
            },
            {
              name: "1-2-1-2",
              key: "1-2-1-2",
              lable: "1-2-1-2",
              children: [],
            },
          ],
        },
        {
          name: "1-2-2",
          key: "1-2-2",
          lable: "1-2-2",
          children: [],
        },
        {
          name: "1-2-3",
          key: "1-2-3",
          lable: "1-2-3",
          children: [],
        },
      ],
    },
  ]) as any;
  return {
    treeData
  }
}

使用:

<!--
 * @Date: 2022-10-27 15:46:26
 * @LastEditors: zhangsk
 * @LastEditTime: 2022-11-16 11:24:47
 * @FilePath: \basic-demo\src\pages\index.vue
 * @Label: Do not edit
-->
<template>
  <div class="container">
    <h1>hello,World!</h1>
    <!-- 公用组件使用 -->
    <CalculateVue
      v-model:value-one="form2.valueOne"
      v-model:value-two="form2.valueTwo"
      v-model:selected="form2.selected"
      @calculate="calculateFun"
    ></CalculateVue>
    <div>{{ form.valueOne }} -{{ form.selected }} - {{ form.valueTwo }}</div>
    <div>计算结果:{{ result ? result : "-" }}</div>
    <!-- 树组件 -->
    <TreeVue :data="treeData"></TreeVue>
    <!-- 透传属性 -->
    <AttributeBoxVue
      class="woshi"
      v-bind="attributes"
      :arr="['1', '2', '3']"
    ></AttributeBoxVue>
    <!-- 插槽 -->
    <SlotBoxVue title="我是父组件传递的标题">
      <template #default="{ text }"> {{ text }}</template>
      <template #footer></template>
    </SlotBoxVue>
    <!-- 动态组件 -->
    <DynamicComponentVue
      :components-arr="componentsArr"
      :form="form"
    ></DynamicComponentVue>
  </div>
</template>
<script lang="ts" setup>
import CalculateVue from "@/components/common/Calculate.vue";
import TreeVue from "@/components/Tree/index.vue";
import AttributeBoxVue from "@/components/common/AttributeBox.vue";
import SlotBoxVue from "@/components/common/SlotBox.vue";
import DynamicComponentVue from "@/components/common/DynamicComponent.vue";

//  使用组合式函数
import useCalculateData from "./data/calculate";
import useTreeData from "./data/tree";
import useAttributeData from "./data/attribute";
import useDynamicData from "./data/dynamic";
//  计算组件
const { form2, result, calculateFun } = useCalculateData();
//  树数据
const { treeData } = useTreeData();
//  透传属性
const { attributes } = useAttributeData();
//  动态组件
const { form, componentsArr } = useDynamicData();
</script>
<style lang="scss" scoped></style>

大功告成!效果:
示例

结语

结束了。使用方法就是这样,如果两个组合式函数直接有联系的话,直接引入使用即可。

Logo

前往低代码交流专区

更多推荐