淺析Vue3中的邏輯復(fù)用
使用了 Vue3 Composables 之后,邏輯復(fù)用比之前要順手很多,這里說(shuō)說(shuō)前端開發(fā)最常用的場(chǎng)景,管理頁(yè)面的列表查詢和增刪改查的邏輯復(fù)用,歡迎大家共同探討。
用免費(fèi)的 render 服務(wù)搭建了個(gè)在線的預(yù)覽地址,源碼在這里,用了免費(fèi)的 node 環(huán)境和免費(fèi)的 pg 數(shù)據(jù)庫(kù),對(duì)這部分有興趣的可以看看我以前的分享,我寫了個(gè)部署 spring-boot 的分享,使用 node 就更簡(jiǎn)單了。
可能每個(gè)人的具體工作內(nèi)容不一致,但是應(yīng)該都完成過(guò)這樣的工作內(nèi)容:
- 列表查詢,帶分頁(yè)和過(guò)濾條件
- 新增,修改,查看,刪除
- 進(jìn)行一些快捷操作,比如:激活、通過(guò)
這些最基礎(chǔ)的工作可能占用了我們很大的時(shí)間和精力,下面來(lái)討論下如何邏輯復(fù)用,提高工作效率
需求分析
一個(gè)后臺(tái)管理中心,絕大部分都是這種管理頁(yè)面,那么需要:
- 首先是封裝一些通用的組件,這樣代碼量最低也容易保持操作邏輯和 UI 的一致性
- 其次要封裝一些邏輯復(fù)用,比如進(jìn)入頁(yè)面就要進(jìn)行一次列表查詢,翻頁(yè)的時(shí)候需要重新查詢
- 最后需要有一些定制化的能力,最基本的列需要自定義,頁(yè)面的過(guò)濾條件和操作也不一樣
統(tǒng)一復(fù)用
- 發(fā)起 http 請(qǐng)求
- 展示后端接口返回的信息,有成功或者參數(shù)校驗(yàn)失敗等信息
列表的查詢過(guò)程
- 頁(yè)面加載后的首次列表查詢
- 頁(yè)面 loading 狀態(tài)的維護(hù)
- 翻頁(yè)的邏輯和翻頁(yè)后的列表重新查詢
- 過(guò)濾條件和模糊搜索的邏輯,還有對(duì)應(yīng)的列表重新查詢
新增 Item、查詢 Item、修改 Item
- form 在提交過(guò)程的禁用狀態(tài)
- 發(fā)起網(wǎng)絡(luò)請(qǐng)求
- 后端接口返回的信息提示
- 列表重新查詢
刪除 Item
- 刪除按鈕狀態(tài)的維護(hù)(需要至少一個(gè)選中刪除按鈕才可用)
- 發(fā)起網(wǎng)絡(luò)請(qǐng)求
- 后端接口返回的信息提示
- 列表重新查詢
定制化的內(nèi)容
- table 的列數(shù)據(jù)
- item 的屬性,也就是具體的表單
- 快捷操作:改變 user 激活狀態(tài)
- 列表的過(guò)濾條件
成果展示

- 打開頁(yè)面會(huì)進(jìn)行一次列表查詢
- 翻頁(yè)或者調(diào)整頁(yè)面數(shù)量,會(huì)進(jìn)行一次列表查詢
- 右上角的是否激活篩選狀態(tài)變更會(huì)進(jìn)行一次列表查詢
- 右上角模糊搜索,輸入內(nèi)容點(diǎn)擊搜索按鈕會(huì)進(jìn)行一次列表查詢
- 點(diǎn)擊左上角的新增,彈出表單對(duì)話框,進(jìn)行 item 的新增
- 點(diǎn)擊操作的“編輯”按鈕,彈出表單對(duì)話框,對(duì)點(diǎn)擊的 item 進(jìn)行編輯
- 點(diǎn)擊“改變狀態(tài)”按鈕,彈出確認(rèn)框,改變 user 的激活狀態(tài)
- 選中列表的 checkbox,可以進(jìn)行刪除
代碼直接貼在下面了,使用邏輯復(fù)用完成以上的內(nèi)容一共 200 多行,大部分是各種縮進(jìn),可以輕松閱讀,還寫了一個(gè) Work 的管理,也很簡(jiǎn)單,證明這套東西復(fù)用起來(lái)沒(méi)有任何難度。
<template>
<div class="user-mgmt">
<biz-table
:operations="operations"
:filters="filters"
:loading="loading"
:columns="columns"
:data="tableData"
:pagination="pagination"
:row-key="rowKey"
:checked-row-keys="checkedRowKeys"
@operate="onOperate"
@filter-change="onFilterChange"
@update:checked-row-keys="onCheckedRow"
@update:page="onUpdatePage"
@update:page-size="onUpdatePageSize"
/>
<user-item :show="showModel" :item-id="itemId" @model-show-change="onModelShowChange" @refresh-list="queryList" />
</div>
</template>
<script setup name="user-mgmt">
import { h, ref, computed } from 'vue';
import urls from '@/common/urls';
import dayjs from 'dayjs';
import { NButton } from 'naive-ui';
import BizTable from '@/components/table/BizTable.vue';
import UserItem from './UserItem.vue';
import useQueryList from '@/composables/useQueryList';
import useDeleteList from '@/composables/useDeleteList';
import useChangeUserActiveState from './useChangeUserActiveState';
// 自定義列數(shù)據(jù)
const columns = [
{
type: 'selection'
},
{
title: '姓',
key: 'firstName'
},
{
title: '名',
key: 'lastName'
},
{
title: '是否激活',
key: 'isActive',
render(row) {
return row.isActive ? '已激活' : '未激活';
}
},
{
title: '創(chuàng)建時(shí)間',
key: 'createdAt'
},
{
title: '更新時(shí)間',
key: 'updatedAt'
},
{
title: '操作',
key: 'actions',
render(row) {
return [
h(
NButton,
{
size: 'small',
onClick: () => onEdit(row),
style: { marginRight: '5px' }
},
{ default: () => '編輯' }
),
h(
NButton,
{
size: 'small',
onClick: () => onChangeUserActiveState(row),
style: { marginRight: '5px' }
},
{ default: () => '改變狀態(tài)' }
)
];
}
}
];
// 自定義右上角篩選
const filters = ref([
{
label: '是否激活',
type: 'select',
value: '0',
class: 'filter-select',
options: [
{
label: '全部',
value: '0'
},
{
label: '已激活',
value: '1'
},
{
label: '未激活',
value: '2'
}
]
},
{
label: '',
type: 'input',
placeholder: '請(qǐng)輸入姓氏',
value: ''
}
]);
// 篩選變化,需要重新查詢列表
const onFilterChange = ({ index, type, value }) => {
filters.value[index].value = value;
queryList();
};
// 自定義查詢列表參數(shù)
const parmas = computed(() => {
return {
isActive: filters.value[0].value,
like: filters.value[1].value
};
});
// 封裝好的查詢列表方法和返回的數(shù)據(jù)
const { data, loading, pagination, onUpdatePage, onUpdatePageSize, queryList } = useQueryList(urls.user.user, parmas);
// 經(jīng)過(guò)處理的列表數(shù)據(jù),用于在 table 中展示
const tableData = computed(() =>
data.value.list.map(item => {
return {
...item,
createdAt: dayjs(item.createdAt).format('YYYY-MM-DD HH:mm:ss'),
updatedAt: dayjs(item.updatedAt).format('YYYY-MM-DD HH:mm:ss')
};
})
);
// 刪除列表相關(guān)邏輯封裝
const { checkedRowKeys, onCheckedRow, deleteList } = useDeleteList({
content: '確定刪除選中的用戶?',
url: urls.user.userDelete,
callback: () => {
queryList();
}
});
// 列表中的快捷操作
const operations = computed(() => {
return [
{
name: 'create',
label: '新增',
type: 'primary'
},
{
name: 'delete',
label: '刪除',
disabled: checkedRowKeys.value.length === 0
}
];
});
// 觸發(fā)操作函數(shù)
const onOperate = function (name) {
operationFucs.get(name)();
};
// 新創(chuàng)建 item
const create = () => {
showModel.value = true;
itemId.value = 0;
};
const onModelShowChange = () => {
showModel.value = !showModel.value;
};
const itemId = ref(0);
// 控制模態(tài)對(duì)話框
const showModel = ref(false);
// 編輯 item
const onEdit = row => {
itemId.value = row.id;
showModel.value = true;
};
const { changeUserActiveState } = useChangeUserActiveState();
// 改變激活狀態(tài)
const onChangeUserActiveState = row => {
changeUserActiveState({
id: row.id,
isActive: !row.isActive,
loading,
callback: () => {
queryList();
}
});
};
// 指定 table 的 rowKey
const rowKey = row => row['id'];
// operation 函數(shù)集合
const operationFucs = new Map();
operationFucs.set('create', create);
operationFucs.set('delete', deleteList);
</script>
<style lang="scss">
.user-mgmt {
height: 100%;
.filter-select {
.biz-select {
width: 100px;
}
}
}
</style>以上就是淺析Vue3中的邏輯復(fù)用的詳細(xì)內(nèi)容,更多關(guān)于Vue邏輯復(fù)用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue 組件組織結(jié)構(gòu)及組件注冊(cè)詳情
這篇文章主要介紹的是Vue 組件組織結(jié)構(gòu)及組件注冊(cè),為了能在模板中使用,這些組件必須先注冊(cè)以便 Vue 能夠識(shí)別。這里有兩種組件的注冊(cè)類型:全局注冊(cè)和局部注冊(cè)。至此,我們的組件都只是通過(guò) Vue.component 全局注冊(cè)的,文章學(xué)詳細(xì)內(nèi)容,需要的朋友可以參考一下2021-10-10
Vue項(xiàng)目頁(yè)面跳轉(zhuǎn)時(shí)瀏覽器窗口上方顯示進(jìn)度條功能
這篇文章主要介紹了Vue項(xiàng)目頁(yè)面跳轉(zhuǎn)時(shí)瀏覽器窗口上方顯示進(jìn)度條功能,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03

