vue3已经出来一段时间了,随着IE的告别vue3也被广泛应用到项目中。就算如此,还是避免不了我们在使用vue3时存在一些的不足的地方,为此,我们不得不去阅读他人总结的文章来查漏补缺。
文章不会很长,大部分会用用例进行描述,耐心看到最后相信你会受益颇多,甚至会触动你重构自己代码的决心。
如果你只是认为本文是怎么教你去设计你的组件,怎么编排你的组件,怎么去优化你的组件,我想跟你说NO!NO!NO,不信请往下看。
需求
本文将通过一个articles业务模块(articles的增删改查,看下图),一步步的去引导怎么去优化自己的代码。
代码
假如这是一个articles/index.vue(简称index.vue),具体业务实现逻辑如下:
<script setup>
import ArticleTable from './components/ArticleTable.vue'
import ArticleFormModal from './components/ArticleTable.vue'
import { onMounted, ref } from 'vue'
/* state */
const visible = ref(false)
const data = ref([])
const initialState = ref()
/* 钩子函数 */
onMounted(() => {
getArticles()
})
/* 交互method */
const openEditFormModal = (init) => {
initialState.value = init
visible.value = true
}
const openCreateFormModal = () => {
visible.value = true
}
// 接口处理 method
const getArticles = () => {}
const onUpdateArticle = () => {}
const onCreateArticle = () => {}
const onDeleteArticle = () => {}
</script>
<template>
<page-layout>
<page-header>
<a-button type="primary" @click="openCreateFormModal">添加</a-button>
</page-header>
<page-content>
<article-table @delete="onDeleteArticle" @edit="openEditFormModal" />
<article-form-modal
:visible="visible"
:initial-state="initialState"
@create="onUpdateArticle"
@update="onCreateArticle"
/>
</page-content>
</page-layout>
</template>
相信一部人会这么写到这里就停了。如果这只是上面那么一个简单的功能,这么写也没有多大问题,阅读起来还是很ok,可问题就在我们的业务偏偏不会这么简单,我们的产品经理日思夜想的怎么给我们添加杂七杂八的需求,我们的index.vue文件将会越来越大,越来越杂,如果不想被队友骂(相信接手别人代码的人总会那么吐槽几句),我们不得不的进一步优化。
Hook 登场
articles/hook.js
import { onMounted, ref } from 'vue'
export const useArticle = () =>
/* state */
const visible = ref(false)
const data = ref([])
const initialState = ref()
/* 钩子函数 */
onMounted(() => {
getArticles()
})
/* 交互method */
const openEditFormModal = (init) => {
initialState.value = init
visible.value = true
}
const openCreateFormModal = () => {
visible.value = true
}
// 接口处理 method
const getArticles = () => {}
const onUpdateArticle = () => {}
const onCreateArticle = () => {}
const onDeleteArticle = () => {}
return {
visible,
data,
initialState,
openEditFormModal,
openCreateFormModal
onUpdateArticle,
onCreateArticle,
onDeleteArticle
}
}
export default article
articles/index.vue
<script setup>
import ArticleTable from './components/ArticleTable.vue'
import ArticleFormModal from './components/ArticleTable.vue'
import { useArticle } from './hook'
const {
visible,
data,
initialState,
openEditFormModal,
openCreateFormModal
onUpdateArticle,
onCreateArticle,
onDeleteArticle
} = useArticle()
</script>
<template>
<page-layout>
<page-header>
<a-button type="primary" @click="openCreateFormModal">添加</a-button>
</page-header>
<page-content>
<article-table @delete="onDeleteArticle" @edit="openEditFormModal" />
<article-form-modal
:visible="visible"
:initial-state="initialState"
@create="onUpdateArticle"
@update="onCreateArticle"
/>
</page-content>
</page-layout>
</template>
看起来不错,我们的index.vue文件简洁了许多,我们某个功能模块的状态值和处理逻辑都整合到了一个js文件,这阅读起来也舒服了许多。
但是我想说的是,这已经是我们优化的尽头了吗。有没有想过以下几个问题:
- 我们每次使用ArticleTable、ArticleFormModal类似的组件都需要填写一个复杂的vue组件,然后通过import引进来(除全局注册的组件之外)。
- 我们的ArticleTable、ArticleFormModal需要通过声明一堆emit来与父组件进行通信。
接下来就是我们的最终优化。
HOOK + component < useHookComponent
自从vue3 引入composition api 以及 hook 以来,我一直就在思考,我们编写hook代码仅仅只能编写一些 state(ref、reactive等)、method而已吗?我们可不可以把component也整合进去。于是就有了以下写法:
articles/index.vue
<script setup>
import { message } from 'ant-design-vue'
import useArticleFormModal from './hooks/useArticleFormModal'
import useArticleTable from './hooks/useArticleTable'
defineOptions({
name: 'Article',
})
const {
openFormModal,
openEditFormModal,
closeFormModal,
FormModal,
} = useArticleFormModal()
const {
onCreate,
onUpdate,
ArticleTable
} = useArticleTable({
openEditFormModal,
})
</script>
<template>
<page-layout>
<template #header>
<page-header>
<a-button type="primary" @click="openFormModal">添加文章</a-button>
</page-header>
</template>
<page-content>
<ArticleTable />
<ArticleFormModal @create-submit="handleCreate" @edit-submit="handleUpdate" />
</page-content>
</page-layout>
</template>
What!!!我们的删除功能业务方法、编辑功能业务方法呢,哪里去了??我们维护的visible值、data值呢???我们可以不在import任何组件,emit也只是在底层的组件里声明了一次,不用反复声明emit来和父组件进行通信。
通过上面的示例,我们就算通过hook来编写我们的组件,也不会让我们的组件和业务逻辑进行隔离,这恰好很符合composition的思想,组合式的API会让你的逻辑更加清晰。
思考
- 这种编写方式适合那种场景?
- 我们的style怎么编写?
- 其它缺点呢?
项目源码
如果喜欢文本,大家可以到此gitee(或者git)给个star。
一个后台管理系统的解决方案,简洁的代码、易扩展的组件,较全的配置环境。
总结
本文主要是介绍业务组件和业务逻辑整合到HOOk中,这种vue3特有的编写方式也许会很大提升你团队的效率。
欢迎大家收藏.