赞
踩
这篇文章将用之前写的增删改查接口渲染到前端页面,这里借助elementui完成页面,效果如下
文档:https://element-plus.gitee.io/zh-CN/guide/installation.html#%E7%8E%AF%E5%A2%83%E6%94%AF%E6%8C%81
# 选择一个你喜欢的包管理器
# NPM
$ npm install element-plus --save
# Yarn
$ yarn add element-plus
# pnpm
$ pnpm install element-plus
我这里直接上代码了,在Table.vue中直接粘贴即可
<template> <el-button type="primary" plain @click="dialogFormVisible = true" >新增</el-button > <!-- 表格 --> <el-table :data="tableData"> <el-table-column prop="name" label="Name" /> <el-table-column prop="age" label="Age" /> <el-table-column fixed="right" label="Operations" width="120"> <template #default> <el-button type="text" size="small" @click="handleClick" >Delete</el-button > <el-button type="text" size="small">Edit</el-button> </template> </el-table-column> </el-table> <!-- 弹窗 --> <el-dialog v-model="dialogFormVisible" title="Shipping address"> <el-form :model="form"> <el-form-item label="Name" :label-width="formLabelWidth"> <el-input v-model="form.name" autocomplete="off" /> </el-form-item> <el-form-item label="Age" :label-width="formLabelWidth"> <el-input v-model="form.age" autocomplete="off" /> </el-form-item> </el-form> <template #footer> <span class="dialog-footer"> <el-button @click="dialogFormVisible = false">Cancel</el-button> <el-button type="primary" @click="dialogFormVisible = false" >Confirm</el-button > </span> </template> </el-dialog> </template> <script lang="ts" setup> import { reactive, ref, onMounted } from "vue"; import { getList } from "@/components/axiosTable"; const dialogTableVisible = ref(false); const dialogFormVisible = ref(false); const formLabelWidth = "140px"; const form = reactive({ name: "", age: "", }); const tableData = ref([ { name:'TOM', agr:10 }, { name:'TOM1', agr:11 } ]); </script> <style lang="less"> </style>
效果是这样的
弹窗效果
$ yarn add axios
or
$ npm i --save axios
//axios/request.js import axios from "axios"; import type { RequestConfig, RequestInterceptors, CancelRequestSource, } from "./type"; import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios"; class Request { // axios的实例 instance: AxiosInstance; // 拦截器对象 interceptorsObj?: RequestInterceptors; /** * 存放取消方法的集合 * 在创建请求后将取消请求方法 push 到该集合中 * 封装一个方法,可以取消请求,传入 url: string|string[] * 在请求之前判断同一URL是否存在,如果存在就取消请求 */ cancelRequestSourceList?: CancelRequestSource[]; /** * 存放所有请求URL的集合 * 请求之前需要将url push到该集合中 * 请求完毕后将url从集合中删除 * 添加在发送请求之前完成,删除在响应之后删除 */ requestUrlList?: string[]; constructor(config: RequestConfig) { // 数据初始化 this.requestUrlList = []; this.cancelRequestSourceList = []; this.instance = axios.create(config); this.interceptorsObj = config.interceptors; // 拦截器 拦截器的执行顺序为实例请求→类请求→实例响应→类响应 this.instance.interceptors.request.use( (res: AxiosRequestConfig) => { console.log("全局请求拦截器"); return res; }, (err: any) => err ); // 实例拦截器 this.instance.interceptors.request.use( this.interceptorsObj?.requestInterceptors, this.interceptorsObj?.requestInterceptorsCatch ); this.instance.interceptors.response.use( this.interceptorsObj?.responseInterceptors, this.interceptorsObj?.responseInterceptorsCatch ); // 全局响应拦截器最后执行 this.instance.interceptors.response.use( // 因为接口的数据都在res.data下,直接返回res.data即可 (res: AxiosResponse) => { console.log("全局响应拦截器"); return res.data; }, (err: any) => err ); } // 接口拦截 request<T>(config: RequestConfig): Promise<T> { return new Promise((resolve, reject) => { //单个请求的拦截器 if (config.interceptors?.requestInterceptors) { config = config.interceptors.requestInterceptors(config); } const url = config.url; // url存在保存取消请求方法和当前请求url if (url) { this.requestUrlList?.push(url); config.cancelToken = new axios.CancelToken((c) => { this.cancelRequestSourceList?.push({ [url]: c, }); }); } this.instance .request<any, T>(config) .then((res) => { //单个相应拦截器 if (config.interceptors?.responseInterceptors) { res = config.interceptors.responseInterceptors<T>(res); } resolve(res); }) .catch((err: any) => { reject(err); }) .finally(() => { url && this.delUrl(url); }); }); } /** * @description: 获取指定 url 在 cancelRequestSourceList 中的索引 * @param {string} url * @returns {number} 索引位置 */ private getSourceIndex(url: string): number { return this.cancelRequestSourceList?.findIndex( (item: CancelRequestSource) => { return Object.keys(item)[0] === url; } ) as number; } /** * @description: 删除 requestUrlList 和 cancelRequestSourceList * @param {string} url * @returns {*} */ private delUrl(url: string) { const urlIndex = this.requestUrlList?.findIndex((u) => u === url); const sourceIndex = this.getSourceIndex(url); // 删除url和cancel方法 urlIndex !== -1 && this.requestUrlList?.splice(urlIndex as number, 1); sourceIndex !== -1 && this.cancelRequestSourceList?.splice(sourceIndex as number, 1); } /** * 取消全部请求 */ cancelAllRequest() { this.cancelRequestSourceList?.forEach((source) => { const key = Object.keys(source)[0]; source[key](); }); } /** 取消请求 */ cancelRequest(url: string | string[]) { if (typeof url === "string") { // 取消单个请求 const sourceIndex = this.getSourceIndex(url); sourceIndex >= 0 && this.cancelRequestSourceList?.[sourceIndex][url](); } else { // 存在多个需要取消请求的地址 url.forEach((u) => { const sourceIndex = this.getSourceIndex(u); sourceIndex >= 0 && this.cancelRequestSourceList?.[sourceIndex][u](); }); } } } export default Request;
//axios/type.ts // *实例拦截器 为保证封装的灵活性(因为拦截后传参可能不一样) import type { AxiosRequestConfig, AxiosResponse } from "axios"; //基础拦截器 export interface RequestInterceptors { // 请求拦截 requestInterceptors?: (config: AxiosRequestConfig) => AxiosRequestConfig; requestInterceptorsCatch?: (err: any) => any; // 响应拦截 responseInterceptors?: <T = AxiosResponse>(config: T) => T; responseInterceptorsCatch?: (err: any) => any; } //自定义传入的参数 因为axios提供的AxiosRequestConfig不允许传入拦截器 export interface RequestConfig extends AxiosRequestConfig { interceptors?: RequestInterceptors; } //取消请求方法的接口定义 export interface CancelRequestSource { [index: string]: () => void; }
//axios/index.ts import Request from "./request"; import type { RequestConfig } from "./type"; interface MyRequestConfig<T> extends RequestConfig { data?: T; } interface MyResponse<T> { code: number; message: string; data?: T; } // 封装请求方法 const request = new Request({ // baseURL: "import.meta.url", baseURL: "http://localhost:3000/", timeout: 1000 * 60 * 5, interceptors: { // 请求拦截器 requestInterceptors: (config) => { console.log("实例请求拦截器"); return config; }, // 响应拦截器 responseInterceptors: (result) => { console.log("实例响应拦截器"); return result; }, }, }); /** * *发送网络请求 * @description: 函数的描述 * @interface D 请求参数的interface * @interface T 响应结构的intercept * @param {MyRequestConfig} config 不管是GET还是POST请求都使用data * @returns {Promise} */ const myRequest = <D, T = any>(config: MyRequestConfig<D>) => { const { method = "GET" } = config; if (method === "get" || method === "GET") { config.params = config.data; } return request.request<MyResponse<T>>(config); }; export default myRequest; // 取消请求 export const cancelRequest = (url: string | string[]) => { return request.cancelRequest(url); }; // 取消全部请求 export const cancelAllRequest = () => { return request.cancelAllRequest(); };
当前了名字自定义,取的时候路径别错了就行
代码
import request from "@/components/axios/index"; interface Req { name: string; age: string; id: string; } // 查询 export const getList = (data: Partial<Req>) => { return request<any, any>({ url: "users/list", method: "get", data, }); }; // 增加 export const addPeople = (data: Pick<Req, 'name' | 'age'>) => { return request<any, any>({ url: "users/add", method: "post", data, }); }; // 修改 export const updatePeople = (data: Req) => { return request<any, any>({ url: "users/update", method: "post", data, }); }; //删除 export const delPeople = (id: string) => { return request<any, any>({ url: "users/del", method: "get", data: { id }, }); };
- url 为之前写的接口的名称
- method为请求方法
- data为请求参数
一定要确保后端服务启动了,不然一定会调取失败
我将代码需要注意的地方都打上了注释,感觉这块就是调取上面文件里的方法,这块我就直接贴代码,不细说了,有问题欢迎评论区留言哈
<template> <el-button type="primary" plain @click="addClick">新增</el-button> <!-- 表格 --> <el-table :data="tableData"> <el-table-column prop="name" label="Name" /> <el-table-column prop="age" label="Age" /> <el-table-column fixed="right" label="Operations" width="120"> <template #default="scope"> <el-button type="text" size="small" @click="delClick(scope)" >Delete</el-button > <el-button type="text" size="small" @click="editClick(scope)" >Edit</el-button > </template> </el-table-column> </el-table> <!-- 弹窗 --> <el-dialog v-model="dialogFormVisible" title="Shipping address"> <el-form :model="form"> <el-form-item label="Name" :label-width="formLabelWidth"> <el-input v-model="form.name" autocomplete="off" /> </el-form-item> <el-form-item label="Age" :label-width="formLabelWidth"> <el-input v-model="form.age" autocomplete="off" /> </el-form-item> </el-form> <template #footer> <span class="dialog-footer"> <el-button @click="dialogFormVisible = false">Cancel</el-button> <el-button type="primary" @click="handleSubmit">Confirm</el-button> </span> </template> </el-dialog> </template> <script lang="ts" setup> import { reactive, ref, onMounted } from "vue"; import { getList, updatePeople, addPeople, delPeople, } from "@/components/axiosTable"; const dialogFormVisible = ref(false); const formLabelWidth = "140px"; const tableData = ref(); let form = reactive({ id: null, name: "", age: "", }); /** * 重置form */ function resetForm() { form.id = null; form.name = ""; form.age = ""; } /** 打开弹窗 添加 */ function addClick() { dialogFormVisible.value = true; // 一定要记得把form重置,不然会有上次修改赋值的数据 resetForm(); } /** * 弹窗保存 */ async function handleSubmit() { dialogFormVisible.value = false; // 修改 if (form.id) { await updatePeople(form); } else { //新增 let { id, ...data } = form; await addPeople(data); } let { data } = await getList(); tableData.value = data; } // 删除 async function delClick({ row }) { await delPeople(row._id); let { data } = await getList(); tableData.value = data; } /** 打开弹窗 修改 */ function editClick({ row }) { form.id = row._id; form.name = row.name; form.age = row.age; dialogFormVisible.value = true; } onMounted(async () => { let { data } = await getList(); tableData.value = data; }); </script> <style lang="less"></style>
ok,效果已经实现了,可以自己点点试试,我把项目传在了gitee上:https://gitee.com/zdp970719/v3demo,也可以直接拷我的项目
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。