利用vue3+ts實(shí)現(xiàn)管理后臺(tái)(增刪改查)
簡(jiǎn)單的管理后臺(tái)基本上就是數(shù)據(jù)的增刪改查。主要就是 列表 + form 表單。每個(gè)頁(yè)面的邏輯基本上都相同。不同的地方就是每個(gè)頁(yè)面需要調(diào)用的具體 API 及參數(shù)。
以前 vue2 的時(shí)候最簡(jiǎn)單的做法是寫(xiě)出來(lái)一個(gè)頁(yè)面的邏輯,然后直接 copy 到各個(gè)頁(yè)面中,修改 API 及參數(shù)即可。高級(jí)一點(diǎn)的是利用 mixin 函數(shù),將可復(fù)用邏輯抽離,每個(gè)頁(yè)面引入 mixin。
vue3 之后新增了composition API。本文就是利用composition API,將可復(fù)用的邏輯抽離到composition API中,并引入ts,實(shí)現(xiàn)一個(gè)簡(jiǎn)單的管理后臺(tái)功能。
利用@vue/cli創(chuàng)建項(xiàng)目
首先需要將 @vue/cli 升級(jí)到最新版。本文用的是4.5.6版本。
vue create admin cd admin npm run serve
create選擇手動(dòng)選擇Manually select features,會(huì)有一些交互性的選擇,是否要安裝router、vuex等選項(xiàng),空格可以切換是否選中。我們選中TypeScript、Router、Vuex、CSS Pre-processors。
我們利用axios + axios-mock-adapter + mockjs來(lái)進(jìn)行接口請(qǐng)求、接口模擬及假數(shù)據(jù)生成,接下來(lái)再安裝這幾個(gè)包。
npm install axios npm install -D axios-mock-adapter mockjs
項(xiàng)目整體框架
假設(shè)我們的項(xiàng)目包含一個(gè) Header,Header 的作用是切換頁(yè)面。兩個(gè)頁(yè)面,分別為 List 和 About,這兩個(gè)頁(yè)面都是簡(jiǎn)單的列表+增刪改查的操作。
路由
需要在 router 中增加一個(gè) list 的路由信息。
const routes: Array<RouteRecordRaw> = [ { path: '/', name: 'Home', component: Home, }, { path: '/about', name: 'About', component: () => { return import(/* webpackChunkName: "about" */ '../views/About.vue'); }, }, { path: '/list', name: 'List', component: () => { return import(/* webpackChunkName: "list" */ '../views/List.vue'); }, }, ];
列表頁(yè)
首先把列表頁(yè)的結(jié)構(gòu)寫(xiě)出來(lái),List 和 About 的結(jié)構(gòu)大體相似。
<template> <div class='content_page'> <div class='content_body'> <div class='content_button'> <button class='add primary' @click='addItem' title='添加'>添加</button> </div> <div class='content_table'> <table> <thead> <tr> <th v-for='item in thead' :key='item'>{{item}}</th> </tr> </thead> <tbody> <tr v-for='(item, index) in list' :key='item.id'> <td> <span :title='item.id'>{{item.id}}</span> </td> <td> <div v-if='index === currentIndex'> <input v-model='item.name' title='name' /> </div> <span :title='item.name' v-else>{{item.name}}</span> </td> <td :title='item.sex'> <div v-if='index === currentIndex'> <input v-model='item.sex' title='sex' /> </div> <span :title='item.sex' v-else>{{item.sex ? '男' : '女'}}</span> </td> <td :title='item.birth'> <div v-if='index === currentIndex'> <input v-model='item.birth' title='birth' /> </div> <span :title='item.birth' v-else>{{item.birth}}</span></td> <td :title='item.address'> <div v-if='index === currentIndex'> <input v-model='item.address' title='birth' /> </div> <span :title='item.address' v-else>{{item.address}}</span> </td> <td> <div v-if='index === currentIndex'> <button class='primary confirm' @click='confirm(item)' >確定</button> <button @click='cancel(item)' >取消</button> </div> <span v-else> <span @click='editItem(index)'> edit </span> <span @click='deleteItem(index, item)'>delete</span> </span> </td> </tr> </tbody> </table> </div> </div> </div> </template>
其中用到了addItem、editItem、deleteItem、confirm、cancel這幾個(gè)方法,每個(gè)列表頁(yè)的這幾個(gè)方法功能都是相同的,唯一的不同就是請(qǐng)求的 API,我們可以將這幾個(gè) API 做為參數(shù),將增刪改查的方法提取到setup函數(shù)中,做到復(fù)用。接下來(lái)就來(lái)到重點(diǎn)的composition API。
composition API具體實(shí)現(xiàn)
import { ref, onMounted } from 'vue'; import {ItemType, FetchType, DeleteType, AddType, EditType} from '../../types/index'; export const compositionApi = ( fetchApi: FetchType, deleteApi: DeleteType, confirmAddApi: AddType, confirmEditApi: EditType, itemData: ItemType, ) => { const currentIndex = ref<number | null>(null); const list = ref([{}]); const getList = () => { fetchApi().then((res: any) => { list.value = res.data.list; }); }; const addItem = () => { list.value.unshift(itemData); currentIndex.value = 0; }; const editItem = (index: number) => { currentIndex.value = index; }; const deleteItem = (index: number, item: ItemType) => { deleteApi(item).then(() => { list.value.splice(index, 1); // getList(); }); }; const cancel = (item: ItemType) => { currentIndex.value = null; if (!item.id) { list.value.splice(0, 1); } }; const confirm = (item: ItemType) => { const api = item.id ? confirmEditApi : confirmAddApi; api(item).then(() => { getList(); cancel(item); }); }; onMounted(() => { getList(); }); return { list, currentIndex, getList, addItem, editItem, deleteItem, cancel, confirm, }; }; export default compositionApi;
接下來(lái)就是在 List 和 About 頁(yè)面中的setup方法中引入即可。
<script lang='ts'> import axios from 'axios'; import { defineComponent, reactive } from 'vue'; import { compositionApi } from '../components/composables/index'; import {ItemType} from '../types/index'; const ListComponent = defineComponent({ name: 'List', setup() { const state = reactive({ itemData: { id: '', name: '', sex: 0, birth: '', address: '', }, }); const fetchApi = () => { return axios.get('/users'); }; const deleteApi = (item: ItemType) => { return axios.post('/users/delete', { id: item.id }); }; const confirmAddApi = (item: ItemType) => { return axios.post('/users/add', { name: item.name, birth: item.birth, address: item.address, }); }; const confirmEditApi = (item: ItemType) => { return axios.post('/users/edit', { id: item.id, name: item.name, birth: item.birth, address: item.address, }); }; const localPageData = compositionApi(fetchApi, deleteApi, confirmAddApi, confirmEditApi, state.itemData); return { state, ...localPageData, }; }, data() { return { thead: [ 'id', 'name', 'sex', 'birth', 'address', 'option', ], }; } });
這樣 List 頁(yè)面的邏輯基本上就完成了。同樣,About 頁(yè)面的邏輯也就完成了,不同的就是在 About 頁(yè)面更改一下接口請(qǐng)求的地址。
最終實(shí)現(xiàn)效果
composition API vs Mixin
在vue3之前,代碼復(fù)用的話(huà)一般都是用mixin,但是mixin相比于composition API的劣勢(shì),在官網(wǎng)中的解釋如下:
- mixin很容易發(fā)生沖突:因?yàn)槊總€(gè)特性的屬性都被合并到同一個(gè)組件中,所以為了避免 property名沖突和調(diào)試,你仍然需要了解其他每個(gè)特性。
- 可重用性是有限的:我們不能向mixin傳遞任何參數(shù)來(lái)改變它的邏輯,這降低了它們?cè)诔橄筮壿嫹矫娴撵`活性
源代碼
項(xiàng)目中用到的一些 TS 接口的定義、模擬數(shù)據(jù)及接口請(qǐng)求本文中沒(méi)有具體介紹,如果想了解的話(huà)可以去看看源碼。
戳這里:vue3_ts_admin
到此這篇關(guān)于利用vue3+ts實(shí)現(xiàn)管理后臺(tái)(增刪改查)的文章就介紹到這了,更多相關(guān)vue3 TypeScript 管理后臺(tái)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue中的計(jì)算屬性的使用和vue實(shí)例的方法示例
本篇文章主要介紹了vue計(jì)算屬性的使用和vue實(shí)例的方法示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-12-12如何通過(guò)點(diǎn)擊按鈕切換顯示不同echarts圖表
這篇文章主要介紹了如何通過(guò)點(diǎn)擊按鈕切換顯示不同echarts圖表,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10vue中post請(qǐng)求以a=a&b=b 的格式寫(xiě)遇到的問(wèn)題
這篇文章主要介紹了vue中post請(qǐng)求以a=a&b=b 的格式寫(xiě)遇到的問(wèn)題,需要的朋友可以參考下2018-04-04Vue.set與this.$set的用法與使用場(chǎng)景介紹
Vue.set()和this.$set()這兩個(gè)api的實(shí)現(xiàn)原理基本一模一樣,都是使用了set函數(shù),下面這篇文章主要給大家介紹了關(guān)于Vue.set與this.$set的用法與使用場(chǎng)景,需要的朋友可以參考下2022-03-03Vue中router-view和component :is的區(qū)別解析
這篇文章主要介紹了Vue中router-view和component :is的區(qū)別解析,router-view用法直接填寫(xiě)跳轉(zhuǎn)路由,路由組件會(huì)渲染<router-view></router-view>標(biāo)簽,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10Vue文件下載進(jìn)度條的實(shí)現(xiàn)過(guò)程
這篇文章主要介紹了Vue文件下載進(jìn)度條的實(shí)現(xiàn)原理,通過(guò)使用onDownloadProgress方法API獲取進(jìn)度及文件大小等數(shù)據(jù),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07