简单的管理后台基本上就是数据的增删改查。主要就是 列表 + form 表单。每个页面的逻辑基本上都相同。不同的地方就是每个页面需要调用的具体 API 及参数。
以前 vue2 的时候最简单的做法是写出来一个页面的逻辑,然后直接 copy 到各个页面中,修改 API 及参数即可。高级一点的是利用 mixin 函数,将可复用逻辑抽离,每个页面引入 mixin。
vue3 之后新增了composition API。本文就是利用composition API,将可复用的逻辑抽离到composition API中,并引入ts,实现一个简单的管理后台功能。
利用@vue/cli创建项目
首先需要将 @vue/cli 升级到最新版。本文用的是4.5.6版本。
vue create admin cd admin npm run serve
create选择手动选择Manually select features,会有一些交互性的选择,是否要安装router、vuex等选项,空格可以切换是否选中。我们选中TypeScript、Router、Vuex、CSS Pre-processors。
我们利用axios + axios-mock-adapter + mockjs来进行接口请求、接口模拟及假数据生成,接下来再安装这几个包。
npm install axios npm install -D axios-mock-adapter mockjs
项目整体框架
假设我们的项目包含一个 Header,Header 的作用是切换页面。两个页面,分别为 List 和 About,这两个页面都是简单的列表+增删改查的操作。
路由
需要在 router 中增加一个 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'); }, }, ];
列表页
首先把列表页的结构写出来,List 和 About 的结构大体相似。
<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 "htmlcode">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 "htmlcode"><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 页面的逻辑基本上就完成了。同样,About 页面的逻辑也就完成了,不同的就是在 About 页面更改一下接口请求的地址。
最终实现效果
composition API vs Mixin
在vue3之前,代码复用的话一般都是用mixin,但是mixin相比于composition API的劣势,在官网中的解释如下:
- mixin很容易发生冲突:因为每个特性的属性都被合并到同一个组件中,所以为了避免 property名冲突和调试,你仍然需要了解其他每个特性。
- 可重用性是有限的:我们不能向mixin传递任何参数来改变它的逻辑,这降低了它们在抽象逻辑方面的灵活性
源代码
项目中用到的一些 TS 接口的定义、模拟数据及接口请求本文中没有具体介绍,如果想了解的话可以去看看源码。
戳这里:vue3_ts_admin
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新日志
- 中国武警男声合唱团《辉煌之声1天路》[DTS-WAV分轨]
- 紫薇《旧曲新韵》[320K/MP3][175.29MB]
- 紫薇《旧曲新韵》[FLAC/分轨][550.18MB]
- 周深《反深代词》[先听版][320K/MP3][72.71MB]
- 李佳薇.2024-会发光的【黑籁音乐】【FLAC分轨】
- 后弦.2012-很有爱【天浩盛世】【WAV+CUE】
- 林俊吉.2012-将你惜命命【美华】【WAV+CUE】
- 晓雅《分享》DTS-WAV
- 黑鸭子2008-飞歌[首版][WAV+CUE]
- 黄乙玲1989-水泼落地难收回[日本天龙版][WAV+CUE]
- 周深《反深代词》[先听版][FLAC/分轨][310.97MB]
- 姜育恒1984《什么时候·串起又散落》台湾复刻版[WAV+CUE][1G]
- 那英《如今》引进版[WAV+CUE][1G]
- 蔡幸娟.1991-真的让我爱你吗【飞碟】【WAV+CUE】
- 群星.2024-好团圆电视剧原声带【TME】【FLAC分轨】