Vue3的组合式函数
vue2的时候,以一个vue文件是按照vue给的模块文件来写的,也就是选项式API写法(一个文件里有template、script、style)。现在vue3新出了一个组合式API写法(一个文件里有template、script、style)。两者区别主要在script部分,选项式API写法中,script是已经预设了属性方法使用方式的,例data、components、computer、watc
简言
今天来学习下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>
大功告成!效果:
结语
结束了。使用方法就是这样,如果两个组合式函数直接有联系的话,直接引入使用即可。
更多推荐
所有评论(0)