利用vue3+ts实现管理后台(增删改查)


Posted in Javascript onOctober 30, 2020

 简单的管理后台基本上就是数据的增删改查。主要就是 列表 + 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 ? '男' : '女'}}</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这几个方法,每个列表页的这几个方法功能都是相同的,唯一的不同就是请求的 API,我们可以将这几个 API 做为参数,将增删改查的方法提取到setup函数中,做到复用。接下来就来到重点的composition API。

composition API具体实现

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;

接下来就是在 List 和 About 页面中的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 页面的逻辑基本上就完成了。同样,About 页面的逻辑也就完成了,不同的就是在 About 页面更改一下接口请求的地址。

最终实现效果

利用vue3+ts实现管理后台(增删改查)

composition API vs Mixin

在vue3之前,代码复用的话一般都是用mixin,但是mixin相比于composition API的劣势,在官网中的解释如下:

  • mixin很容易发生冲突:因为每个特性的属性都被合并到同一个组件中,所以为了避免 property名冲突和调试,你仍然需要了解其他每个特性。
  • 可重用性是有限的:我们不能向mixin传递任何参数来改变它的逻辑,这降低了它们在抽象逻辑方面的灵活性

源代码

项目中用到的一些 TS 接口的定义、模拟数据及接口请求本文中没有具体介绍,如果想了解的话可以去看看源码。

戳这里:vue3_ts_admin

到此这篇关于利用vue3+ts实现管理后台(增删改查)的文章就介绍到这了,更多相关vue3 TypeScript 管理后台内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
JavaScript 基于原型的对象(创建、调用)
Oct 16 Javascript
JavaScript 实现类的多种方法实例
May 01 Javascript
js操纵dom生成下拉列表框的方法
Feb 24 Javascript
js数组方法扩展实现数组统计函数
Apr 09 Javascript
js变量、作用域及内存详解
Sep 23 Javascript
JavaScript中Cookie操作实例
Jan 09 Javascript
javascript实现C语言经典程序题
Nov 29 Javascript
jquery实时获取时间的简单实例
Jan 26 Javascript
require.js中的define函数详解
Jul 10 Javascript
mpvue将vue项目转换为小程序
Sep 30 Javascript
详解VUE里子组件如何获取父组件动态变化的值
Dec 26 Javascript
javascript设计模式 ? 命令模式原理与用法实例分析
Apr 20 Javascript
vue项目页面嵌入代码块vue-prism-editor的实现
Oct 30 #Javascript
解决vue侦听器watch,调用this时出现undefined的问题
Oct 30 #Javascript
vue2.0 watch里面的 deep和immediate用法说明
Oct 30 #Javascript
JavaScript实现轮播图效果
Oct 30 #Javascript
vue组件添加事件@click.native操作
Oct 30 #Javascript
解决removeEventListener 无法清除监听的问题
Oct 30 #Javascript
详解 javascript对象创建模式
Oct 30 #Javascript
You might like
第四章 php数学运算
2011/12/30 PHP
PHP使用SOAP扩展实现WebService的方法
2016/04/01 PHP
Smarty模板引擎缓存机制详解
2016/05/23 PHP
php常用字符函数实例小结
2016/12/29 PHP
Laravel如何同时连接多个数据库详解
2019/08/13 PHP
为jQuery增加join方法的实现代码
2010/11/28 Javascript
jQuery中使用了document和window哪些属性和方法小结
2011/09/13 Javascript
javascript 循环调用示例介绍
2013/11/20 Javascript
asm.js使用示例代码
2013/11/28 Javascript
动态加载jquery库的方法
2014/02/12 Javascript
在JavaScript中使用timer示例
2014/05/08 Javascript
DOM节点的替换或修改函数replaceChild()用法实例
2015/01/12 Javascript
JavaScript 里的类数组对象
2015/04/08 Javascript
jQuery实现的调整表格行tr上下顺序
2016/01/10 Javascript
JavaScript实现跑马灯抽奖活动实例代码解析与优化(二)
2016/02/16 Javascript
安装使用Mongoose配合Node.js操作MongoDB的基础教程
2016/03/01 Javascript
jquery注册文本框获取焦点清空,失去焦点赋值的简单实例
2016/09/08 Javascript
angularjs中的$eval方法详解
2017/04/24 Javascript
深入理解vue-router之keep-alive
2017/08/31 Javascript
JavaScript中错误正确处理方式小结你用对了吗
2017/10/10 Javascript
微信小程序实现弹出层效果
2020/05/26 Javascript
微信小程序实现左滑动删除效果
2020/03/30 Javascript
小程序识别身份证,银行卡,营业执照,驾照的实现
2019/11/05 Javascript
vue中keep-alive,include的缓存问题
2019/11/26 Javascript
JavaScript的垃圾回收机制与内存管理
2020/08/06 Javascript
python中sys.argv参数用法实例分析
2015/05/20 Python
Python的GUI框架PySide的安装配置教程
2016/02/16 Python
Python的包管理器pip更换软件源的方法详解
2016/06/20 Python
将数据集制作成VOC数据集格式的实例
2020/02/17 Python
美国领先的精品家居照明和装饰产品在线零售商:LightsOnline.com
2018/01/23 全球购物
俄罗斯领先的移动和数字设备在线商店:Svyaznoy.ru
2020/12/21 全球购物
上海方立数码笔试题
2013/10/18 面试题
护士岗位职责
2014/02/16 职场文书
毕业生面试求职信
2014/06/23 职场文书
未婚证明范本
2015/06/15 职场文书
Python re.sub 反向引用的实现
2021/07/07 Python