利用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 相关文章推荐
用jQuery实现检测浏览器及版本的脚本代码
Jan 22 Javascript
设为首页和收藏的Javascript代码(亲测兼容IE,Firefox,chrome等浏览器)
Nov 18 Javascript
基于jQuery实现复选框的全选 全不选 反选功能
Nov 24 Javascript
jquery实现页面关键词高亮显示的方法
Mar 12 Javascript
javascript删除元素节点removeChild()用法实例
May 26 Javascript
JS实现简单的图书馆享元模式实例
Jun 30 Javascript
ES6入门教程之let和const命令详解
May 17 Javascript
详解webpack-dev-server使用http-proxy解决跨域问题
Jan 13 Javascript
从零撸一个pc端vue的ui组件库( 计数器组件 )
Aug 08 Javascript
使用zrender.js绘制体温单效果
Oct 31 Javascript
js实现网页版贪吃蛇游戏
Feb 22 Javascript
vue flex 布局实现div均分自动换行的示例代码
Aug 05 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抓即时股票信息
2006/10/09 PHP
PHP导入Excel到MySQL的方法
2011/04/23 PHP
基于PHP常用字符串的总结(待续)
2013/06/07 PHP
Javascript 兼容firefox的一些问题
2009/05/21 Javascript
js 动态选中下拉框
2009/11/26 Javascript
基于jQuery的为attr添加id title等效果的实现代码
2011/04/20 Javascript
jquery实现非叠加式的搜索框提示效果
2014/01/07 Javascript
我用的一些Node.js开发工具、开发包、框架等总结
2014/09/25 Javascript
JavaScript中的对象序列化介绍
2014/12/30 Javascript
jquery插件uploadify多图上传功能实现代码
2016/08/12 Javascript
javascript self对象使用详解
2016/10/18 Javascript
js实现随机点名小功能
2017/08/17 Javascript
表格展示利器 Bootstrap Table实例代码
2017/09/06 Javascript
VUE2.0中Jsonp的使用方法
2018/05/22 Javascript
vue项目前端埋点的实现
2019/03/06 Javascript
使用 Vue 实现一个虚拟列表的方法
2019/08/20 Javascript
深入理解令牌认证机制(token)
2019/08/22 Javascript
Vue项目中使用mock.js的完整步骤
2021/01/12 Vue.js
python之从文件读取数据到list的实例讲解
2018/04/19 Python
PyQt5每天必学之组合框
2018/04/20 Python
Python视频爬虫实现下载头条视频功能示例
2018/05/07 Python
使用python PIL库实现简单验证码的去噪方法步骤
2019/05/10 Python
简单了解python PEP的一些知识
2019/07/13 Python
python使用beautifulsoup4爬取酷狗音乐代码实例
2019/12/04 Python
PyTorch 对应点相乘、矩阵相乘实例
2019/12/27 Python
pytorch之ImageFolder使用详解
2020/01/06 Python
python tkinter之 复选、文本、下拉的实现
2020/03/04 Python
浅谈Python3多线程之间的执行顺序问题
2020/05/02 Python
属性与 @property 方法让你的python更高效
2020/09/21 Python
百度软件工程师职位
2013/02/14 面试题
优秀党员先进事迹材料
2014/12/18 职场文书
2015年公司行政后勤工作总结
2015/05/20 职场文书
教师节主持词开场白
2015/05/29 职场文书
基于tensorflow权重文件的解读
2021/05/26 Python
中国十大神话动漫电影排行榜 哪吒登顶 白蛇缘起排第七
2022/03/21 国漫
html中相对位置与绝对位置的具体使用
2022/05/15 HTML / CSS