最近有个新项目要做,也很久没有学习新知识了,就想着拿这个项目学点新东西. 组合式api的目的我觉得就是要更好的组织代码逻辑.让通用逻辑更好的复用.
useDialog
1. 定义dialog组合
# composables/dialog.js
import {
computed
} from 'vue'
// 给使用它的dialog组件定义它的props
export const dialogProps = {
visible: {
type: Boolean,
required: true
}
}
// 定义双向绑定事件
export const dialogEmits = ['update:visible']
// 使用组合
export function useDialog (props, emit) {
const visibleModel = computed({
get () {
return props.visible
},
set (val) {
emit('update:visible', val)
}
})
return {
visibleModel
}
}
复制代码
2. 使用dialog组合
// xxx-dialog.vue 定义某个业务弹框
<template>
<a-modal v-model:visible="visibleModel">
内容
</a-modal>
</template>
<script setup>
import {dialogProps, dialogEmits, useDialog} from '../../composables/dialog'
// 定义和组合 props emits
const props = defineProps({
...dialogProps,
// 其他props
})
const emits = defineEmits([
...dialogEmits,
// 其他事件
])
const {visibleModel} = useDialog(props, emits)
</script>
复制代码
一个最简单的组合就完成了.
useForm
1. 定义Form组合
import {ref} from 'vue'
// 修改了vaildate方法的Form组件, 之前的validate方法不管校验失败和成功都进到then里面,我觉得不好就改成只有校验成功才进then里面
export {bbForm as Form} from '../components/bb-form'
export {Input} from '@arco-design/web-vue'
export {InputNumber} from '@arco-design/web-vue'
export function useForm (key) {
// 需要在模板上定义 <a-form ref="ref_form">
const ref_form = ref(null)
return {
ref_form
}
}
复制代码
2. 使用Form组合
<template>
<bb.Form ref="ref_form" :model="form">
</bb.Form>
</template>
<script setup>
import * as bb from '../../composables/form'
const form = ref({
name: ''
})
const {ref_form} = bb.useForm()
// 使用ref_form.value.validate验证表单
</script>
复制代码
useFormInDialog
如果有这样一个需求, 弹框里加上表单,需要提交一些信息,需要先表单验证再提交.失败不关闭表单,成功后关闭表单. 就可以把上面定义的组合再组合一下.
1.定义useFormInDialog组合
import {ref} from 'vue'
import {Message} from '@arco-design/web-vue'
import {getErrorMessageContent} from '../utils/utils'
// visibleModel 是 useDialog 定义的
// ref_form 是 useForm 定义的
export function useFormInDialog (promise, visibleModel, ref_form = null) {
// 需要控制的表单提交按钮的loading状态
const okLoading = ref(false)
// 使用beforeOk这个方式来控制弹框的显示关闭状态
function beforeOk (done) {
let validatePromise = ref_form ? ref_form.value.bbValidate() : Promise.resolve()
validatePromise
.then(() => {
okLoading.value = true
promise()
.then(() => {
okLoading.value = false
Message.success('操作成功!')
done()
visibleModel ? visibleModel.value = false : ''
})
.catch(err => {
okLoading.value = false
if (Array.isArray(err) && err[0].name === 'ValidateError') {
} else {
Message.error(getErrorMessageContent(err))
}
})
})
.catch(err => {
console.warn('表单校验失败!', err)
okLoading.value = false
})
return false
}
return {
okLoading,
beforeOk
}
}
复制代码
2.使用useFormInDialog组合
<template>
<a-modal
v-model:visible="visibleModel" // Dialog 组合
:ok-loading="okLoading" // FormInDialog 组合
@before-ok="beforeOk" // FormInDialog 组合
>
<template #title>查看和编辑</template>
<bb.Form ref="ref_form" :model="form"> // Form 组合
// 具体表单组件
</bb.Form>
</a-modal>
</template>
<script setup>
import axios from 'axios'
import {inject, ref, reactive} from 'vue'
import * as bb from '../../composables/form'
import {dialogProps, dialogEmits, useDialog} from '../../composables/dialog'
import {useFormInDialog} from '../../composables/form-dialog'
// Dialog组合
const props = defineProps({
...dialogProps,
uuid: {
type: String,
required: true
}
})
const emits = defineEmits([
...dialogEmits,
'edit-success'
])
const {visibleModel} = useDialog(props, emits)
// Form组合
const form = ref({
})
const rules = reactive({
})
const {ref_form} = bb.useForm()
// FormInDialog组合
// 只需要定义好表单的校验规则,只要写少量的业务代码就能完成复用
const {okLoading, beforeOk} = useFormInDialog(() => {
return new Promise(async (resolve, reject) => {
try {
await axios.put(`具体api`, {...form.value})
resolve()
emits('edit-success')
} catch (err) {
reject(err)
}
})
}, visibleModel, ref_form)
</script>
复制代码
总结
组合之后的代码比我之前写vue2的时候更紧凑了. 在如何写业务代码的时候更多了一些思考.