注意:这里拦截器可以找到官方文档内的interceptor下面的代码直接拷贝过来
axios官方文档 / 点击进入
// 该文件是二次封装axios
import axios from 'axios'
// 定义axios默认配置
const request = axios.create({
/*
1、开发环境是跨域环境,上线不会出现跨域问题,baseURL要区分开发和生产
2、开发环境下,baseURL应该为反向代理请求的前缀,但是请求前缀不能直接在request.js赋值
应存储在环境变量中
*/
// proess.env是环境变量,可以在任意位置直接获取,用于判断环境是生产环境还是开发环境
// 下面有一个属性就是NODE_ENV,可以看到是开发还是生产环境
// baseURL: '/api' ⇒ 这样写的话容易固定前缀,无法辨别是开发环境还是生产环境
// 此处使用的是自定义环境变量
baseURL: process.env.VUE_APP_BASE_URL
})
// 添加拦截器
axios.interceptors.request.use(function (config) {
// 获取token 添加到请求头中,发送后端进行接口校验
return config
}, function (error) {
return Promise.reject(error)
})
axios.interceptors.response.use(function (response) {
/*
后端检验token失败返回错误的code,401:token过期,403:未登录
在响应拦截器当中需要判断code,如果token过期或者未登录,弹出错误的提示,
清除本地所有登录相关缓存并重新去登录页
如果不清除不跳转的话token可以在network当中直接进行修改,跳过验证不安全
*/
return response
}, function (error) {
return Promise.reject(error)
})
// 到处request
export default request
注意:反向配置代理中的target目标源是fastmock中的地址,待会会讲如何创建fastmock的在线文件
// 该文件是vue的配置管理
const { defineConfig } = require('@vue/cli-service')
// node内定义path方法
const path = require('path')
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
host: 'localhost',
// 端口号尽量9000以上,防止电脑其他地方占用,或者直接重新修改
port: 9898,
open: true,
/*
配置服务器反向代理解决开发环境,ajax请求跨域问题
反向代理,是由服务器替我们请求目标源
服务器请求target里面的目标源+请求前缀重写后的值+请求中后面的path
/api/a/b
http://api.it120.cc/api/a/b
*/
proxy: {
// 所有的请求path必须以当前前缀开头
'/api': {
// 代理的源
// 这里请求的是fastmock中的地址
target: 'https://www.fastmock.site/mock/27f9ed4811870d97ecf603d848a86ec4/api',
// 是否切换源
changeOrigin: true,
// 前缀路径重写
pathRewrite: {
'^/api': '/api'
}
}
}
},
/*
关闭eslint 保存就检查代码的格式
关闭后,vscode需要安装 eslint 插件,用于检查代码
*/
lintOnSave: false,
// 重新定义快捷键来定位到指定路径,防止层级过深找不到该文件
chainWebpack: config => {
config.resolve.alias
.set('@', path.join(__dirname, 'src'))
.set('@a', path.join(__dirname, 'src/api'))
.set('@c', path.join(__dirname, 'src/components'))
.set('@r', path.join(__dirname, 'src/router'))
.set('@s', path.join(__dirname, 'src/store'))
.set('@u', path.join(__dirname, 'src/utils'))
.set('@v', path.join(__dirname, 'src/views'))
}
})
注意:建议这里文件命名跟views当中对应的请求文件名字相同,方便后期代码维护
// 单独管理 HomePage这个路由组件中所有请求
import request from '@u/request'
const fetchCates = (params = {}) => {
return request.get('请求路径', { params })
}
// 导出fetchCates这个函数,函数方便复用,而且可以携带参数
export {
fetchCates
}
容易跟axios二次封装混淆,注意辨别
const request = axios.create({
baseURL: process.env.NODE_ENV === 'development' ? '/conner' : '生产源'
})
npm i mockjs -D
注意number一定要给一个范围,用于修饰number大小,不然用该语法就毫无意义,可以直接赋值
- 基础类型
boolean, natural, integer, float, character, string, range
日期相关
date, time, datetime, now
图片
img, dataImage
颜色
color, hex, rgb, rgba, hsl
随机文本
paragraph, sentence, word, title, cparagraph, csentence, cword, ctitle
名字
first, last, name, cfirst, clast, cname
web地址相关
url, domain, protocol, tld, email, ip
地址相关
region, province, city, county, zip
其他
capitalize, upper, lower, pick, shuffle
// 引入mockjs
const Mock = require('mockjs')
// 第一个参数:拦截接口的path
// 第二个参数:请求方式
// 第三个参数:对象,写入接口返回的数据
Mock.mock('/api/getItemLists', 'get', {
code: 200,
msg: 'success',
data: {
'total|100-200': 100,
'lists|10': [
{
'id|+1': 1, //id自增1
itemName: '@ctitle', //随机生成商品名
'price|0-1000': 0, //随机生成价格,可以用随机@natural,但是不建议,会生成非常大的数,有点离谱
'sale|0-1000': 0, //随机生成售卖价格
desc: '@cparagraph', //随机生成一段商品描述
onsale: '@boolean', //是否售卖,随机生成布尔值判断是不是在售
thumb: "@img('500x500','@color', '宇宙无敌臀臀')",//随机生成一张图片,随机颜色,固定名称
createAt: '@date' //随机日期
}
]
}
})
这里实际项目我按照会员管理系统搭建的,对应商品增加和删除其实同理
以下该文档简称el
建议将main.js中的创建app实例和渲染等vue自带写了一段长代码分解,因为很多东西要在创建和渲染之间进行,比如这里的国际化,实例还未创建无法使用国家化,渲染之后再使用也不行,所以得放在两者中间
// 引入element-plus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
// 配置element-plus国际化
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
// 创建vue实例
const app = createApp(App)
// 使用element-plus的国际化
app.use(ElementPlus, {
locale: zhCn
})
app.use(store)
app.use(router)
app.mount('#app')
// createApp(App).use(store).use(router).mount('#app')
下面简称aside
)和页面头CommonHeader.vue(下面简称header
)进行分别管理利用vbase快速生成一个模板放在里面,template中编辑对应简单的文字,比如aside中div内加个侧边栏即可,不然后面查看页面时候会出现没有编辑模块的报错,而且没有内容不方便查看布局效果
<template>
<div>
页面头
div>
template>
<script>
export default {
}
script>
<style lang="scss" scoped>
style>
import CommonAside from './components/CommonAside.vue'
import CommonHeader from './components/CommonHeader.vue'
注意:后面查看el中的很多组件和功能要自己进行筛选,这里vbase快捷加入模板中已经自带了template了所以只需要复制里面的内容即可
<template>
<div class="common-layout">
<el-container>
<el-aside width="200px">
<common-aside>common-aside>
el-aside>
<el-container>
<el-header>
<common-header>common-header>
el-header>
<el-main>
<router-view>router-view>
el-main>
el-container>
el-container>
div>
template>
import CommonAside from './components/CommonAside.vue'
import CommonHeader from './components/CommonHeader.vue'
export default {
// 一定要定义一个name跟文件同名,大驼峰命名法,不然文件最上面会飘红
name: 'LayOut',
// 这里引入子组件后在eslint环境下会飘红,注意这里是需要在template中引入组件名才可消除飘红
components: {
CommonAside,
CommonHeader
}
}
<template>
<router-view/>
template>
可以这么理解,app.vue为整个项目的路由出口,其router-view就是路由router文件夹中的内容,在这内容中又把布局单独拿出去,在这里引入,并注册全局组件,相当于app.vue中包裹了整个LayOut的布局,LayOut中又进行了分离,index中引入头和侧边栏,中间的el-main中的router-view则是下面具体的局部组件
import { createRouter, createWebHistory } from 'vue-router'
// 引入首页布局部分
import LayOut from '@/LayOut'
const routes = [
{
path: '/',
name: 'home',
/*
注册全局组件,也就是整个首页的布局放入,同时LayOut中又
有很多子路由,在el-main中的出口显示
*/
children: [
],
component: LayOut
}
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
export default router
由于页面有很多的默认样式,我们在assets当中建立一个css文件夹,内部建立一个reser.css的文件,在网上找到一些合适的默认样式取消的代码cv进来,在main.js中引入
默认样式的css
html, body, div, span, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
abbr, address, cite, code,
del, dfn, em, img, ins, kbd, q, samp,
small, strong, sub, sup, var,
b, i,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, figcaption, figure,
footer, header, hgroup, menu, nav, section, summary,
time, mark, audio, video {
margin:0;
padding:0;
border:0;
outline:0;
font-size:100%;
vertical-align:baseline;
background:transparent;
}
body {
line-height:1;
/* 取消鼠标双击选中文字 */
/* 火狐 */
-moz-user-select: none;
/* Safari 和 欧朋 */
-webkit-user-select: none;
/* IE10+ and Edge */
-ms-user-select: none;
/* Standard syntax 标准语法(谷歌) */
user-select: none;
}
:focus {
outline: 1;
}
article,aside,canvas,details,figcaption,figure,
footer,header,hgroup,menu,nav,section,summary {
display:block;
}
nav ul {
list-style:none;
}
blockquote, q {
quotes:none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content:'';
content:none;
}
a {
margin:0;
padding:0;
border:0;
font-size:100%;
vertical-align:baseline;
background:transparent;
}
ins {
background-color:#ff9;
color:#000;
text-decoration:none;
}
mark {
background-color:#ff9;
color:#000;
font-style:italic;
font-weight:bold;
}
del {
text-decoration: line-through;
}
abbr[title], dfn[title] {
border-bottom:1px dotted #000;
cursor:help;
}
table {
border-collapse:collapse;
border-spacing:0;
}
hr {
display:block;
height:1px;
border:0;
border-top:1px solid #cccccc;
margin:1em 0;
padding:0;
}
input, select {
vertical-align:middle;
}
main.js引入默认css
// 引入css样式表的重置
import './assets/css/reset.css'
.el-container{
height: 100vh;
.el-aside{
background-color: #0f1a30;
}
.el-main{
background-color:red;
padding: 0;
}
.el-header{
background-color:green;
}
}
进入LayOut中的aside,删除之前定义的侧边栏
三个字,引入assets中imgs的logo图片
<template>
<div class="logo">
<img src="../../assets/imgs/logo-full.png" alt="">
div>
template>
设置logo样式让其显示出来
.logo{
height: 66px;
display: flex;
justify-content: center;
align-items: center;
img{
width: 80%;
}
}
进入el
中找到Menu菜单栏中侧栏部分,因为这里我们要的样式是侧栏右边那一种,所以在下面展开的代码当中找到custom colors标题的部分代码cv其中的el-menu中的内容
这里因为代码太多不方便查看可以找到其中的el-sub-menu标签,可以删除几个保留一个
使用el
自带的icon图标,找到el
文件中的icon图标一栏,这里要注意自带的icon需要下载依赖包
// 引入element-plus的图标
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
// 创建vue实例
const app = createApp(App)
// 导入所有图标并进行全局注册
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
<el-icon :size="15"><House />el-icon>
el
中icon下面有一些图标,找到对应图标,点击即可复制,回到aside中找到el-sub-menu下面的el-icon将其替换,就可以改图标了el-menu中默认的几个属性
删除
删除
接下来进入src下的views文件夹创建后面所有要跳转的路由文件,同时在内部建立index.vue文件,同时在index.vue中vbase建立最简单的一个模板,div中加上中文比如:template中div内写上商品分类文字
方便待会查看,添加name,解决飘红问题
回到router的index进行补充,引入这些子路由这里将要写的整个业务所有的子路由写了,注意查看注释
// 创建三个主要页面的路由,主页路由,登录路由,404路由
const routes = [
// 主页路由
{
path: '/',
name: '主页',
// 主页路由下的所有子组件
children: [
{
// 路由重定向到仪表盘
path: '/',
redirect: '/dashBoard'
},
// ------- 店铺管理
{
path: '/storeManagement',
name: '店铺管理',
// es6中的动态引入,实现路由懒加载,组件使用的时候才加载,性能更好
component: () => import('@v/StoreManagement')
},
{
path: '/storeLists',
name: '店铺列表',
component: () => import('@v/StoreLists')
},
{
path: '/staffManagement',
name: '员工管理',
component: () => import('@v/StaffManagement')
},
// ------- 会员管理
{
path: '/memberManagement',
name: '会员管理',
component: () => import('@v/MemberManagement')
},
{
path: '/memberLists',
name: '会员列表',
component: () => import('@v/MemberLists')
},
{
path: '/memberGrade',
name: '会员等级',
component: () => import('@v/MemberGrade')
},
{
path: '/dashBoard',
name: '仪表盘',
component: () => import('@v/DashBoard')
},
{
path: '/setting',
name: '设置',
component: () => import('@v/SettingPage')
}
],
component: LayOut
},
// 404路由组件
{
path: '/:pathMatch(.*)*',
name: '404',
component: () => import('@v/NotFound')
},
// 登录路由组件
{
path: '/login',
name: '登录',
component: () => import('@v/LoginPage')
}
]
配置el-menu中的:default-active = '$route.path'
默认给首页加上激活色
回到aside,将最内部的el-menu-item复制一个放到最外面,作为首页也就是仪表盘,每一次刚进入网站时展示的页面
,不需要下拉栏,将内部的index改成路由地址,这里也就是跳转到仪表盘的子路由,路由出口在LayOut内index中的el-main中已经定义了出口
<el-menu-item index="/dashBoard">
<el-icon><House />el-icon>
<span>首页span>
el-menu-item>
el-menu标签中添加router启用该模式会在激活导航时以 index 作为 path 进行路由跳转 使用 default-active 来设置加载时的激活项
,上面的index本来只是保证唯一性,现在以路由方式启动,所以首页中的index='/dashBoard’会开启路由,自动在router中找到对应的子路由路径进行显示,这时如果点击未定义的一些侧边栏按钮,会跳转到404页面
接下来将所有的下拉栏模板按照样式进行搭建下面以一个为例,其他相同cv更改即可
<el-sub-menu index="1">
<template #title>
<el-icon><ShoppingCart />el-icon>
<span>店铺管理span>
template>
<el-menu-item index="/storeLists">
<template #title><span>店铺列表span>template>
el-menu-item>
<el-menu-item index="/staffManagement">
<template #title><span>员工管理span>template>
el-menu-item>
el-sub-menu>
注意这里在更改css样式的时候如果希望更改el-sub-menu的悬停样式,要单独写style,取消scoped,其余样式自行设计
我这里自己设计了自己想要的样式,就是鼠标悬停的时候背景色字体颜色改变,点击后用:before做的线条,接下来就是补充剩下的侧边栏和路由跳转
删除之前占位的页面头
页面头部主要分为三个部分,头部面包屑栏,右侧用户中心栏,下面的标签栏
定义一个头部标签header,内部一个header-top上栏部分,header-bottom下栏标签栏,header-top中又分为左侧和右侧
<div class="header">
<div class="header-top">
<div class="header-top-fl">
div>
<div class="header-top-fr">
div>
div>
<div class="header-bottom">div>
div>
左侧部分一个可以点击折叠侧边栏的图标,和面包屑,右侧为搜索功能,用户名和头像
首页固定而且有跳转效果是el已经设定好了,只需要改路径即可,后面接着的不需要跳转,所以只需要显示对应路由的name即可,name在路由中定义成中文名了,如果已经跳转到首页,那么后面不需要有任何子栏,所以v-if判断直接隐藏
<div class="header-top-fl">
<el-icon :size="20">
<Fold />
el-icon>
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首页el-breadcrumb-item>
<el-breadcrumb-item v-if="$route.path !== '/dashBoard'">
{{ $route.name }}
el-breadcrumb-item>
el-breadcrumb>
div>
注意这里面包屑的文字滑过更改跟上面同理,需要去除scoped单独设置
右侧部分主要是一个搜索框和用户名以及头像
两个问题:1、头像使用本地图片不进行显示,是因为这里el-avatar是el自己封装的图片,src这里解析本地路径会解析成字符串无法显示,可以给src里面写一个变量,在script中用import在其他里面引入data中定义一下即可。2、下拉栏对应路由跳转的问题,需要给el-dropdown配置@command等于一个变量,el-dropdown-item定义command等于一个值,下面在方法中定义handleCommand接受参数,如果等于a,那么跳转到对应地址
代码如下:
<div class="header-top-fr">
<el-col :span="12">
<el-autocomplete
:fetch-suggestions="querySearch"
clearable
placeholder="请输入搜索内容"
@select="handleSelect"
prefix-icon="search"
/>
el-col>
<p>会员管理系统p>
<div class="user">
<el-dropdown @command="handleCommand">
<div>
<el-avatar :size="35" :src="picture" shape="square"/>
div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="a">
<el-icon :size="15"><UserFilled />el-icon>
<span>个人中心span>
el-dropdown-item>
<el-dropdown-item command="b">
<el-icon :size="15"><Operation />el-icon>
<span>退出登录span>
el-dropdown-item>
el-dropdown-menu>
template>
el-dropdown>
div>
div>
<script>
// 引入头像
import picture from '../../assets/imgs/head-pic.png'
export default {
data () {
return {
picture: picture
}
},
methods: {
// 头像下拉栏中点击对应文字跳转到对应路由
handleCommand (command) {
console.log(command)
if (command === 'a') {
this.$router.push({
path: '/UserInfo'
})
}
},
querySearch () {},
handleSelect () {}
}
}
</script>
底部显示标签部分,也就是点击了哪个页面会在这里存储一份标签
待定!
接下来就是补全一下功能
注意在发布模式的时候要取消严格模式,只是为了让我们在书写代码的时候更加严谨一点
import { createStore } from 'vuex'
// 引入modules中的base文件
import base from './modules/base'
export default createStore({
// 记得开启严格模式,删除前面四个,保留模块,分别在modules中定义,是为了让state中的数据只能在mutation中进行操作
strict: true,
modules: {
base
}
})
export default {
// 让该文件变成带命名空间的文件,必须加namespaced
namespaced: true,
// 数据
state: {
// 导航菜单是否折叠,定义一个变量数据,开始为fasle未折叠
menuCollapse: false
},
// 操作数据
mutations: {
// 注意这里尽量进行大写命名函数,因为导出后可能会和其他命名有冲突,特殊一点,来接收上面的state数据进行操作
TOGGLE_COLLAPSE (state) {
// 给上面的menuCollapse进行取反即可
state.menuCollapse = !state.menuCollapse
}
}
}
// 触发vuex中的mutations方法
toggleMenu () {
// 通过store上的commit方法调用mutations
this.$store.commit('base/TOGGLE_COLLAPSE')
}
<el-icon :size="20" @click="toggleMenu">
<component :is="$store.state.base.menuCollapse?'Expand':'Fold'">component>
el-icon>
<div class="logo">
<img :src="$store.state.base.menuCollapse?require('../../assets/imgs/logo-s.png'):require('../../assets/imgs/logo-full.png')" alt="">
div>
<el-aside :width="$store.state.base.menuCollapse?'56px':'200px'" >
这里遗留一个问题,侧边栏卡顿问题,后面进行处理
结果如下
html部分
<div class="main">
<div class="main-search">
<div class="search-top">
<div>
<span>会员IDspan>
<el-input v-model="input" placeholder="请输入会员ID" clearable />
div>
<div>
<span>手机号span>
<el-input v-model="input" placeholder="请输入会员手机号" clearable />
div>
<div>
<span>名称span>
<el-input v-model="input" placeholder="请输入会员名称" clearable />
div>
<div>
<span>会员等级span>
<el-select v-model="value" placeholder="会员等级">
<el-option
v-for="item in options1"
:key="item.value"
:label="item.label"
:value="item.value"
/>
el-select>
div>
div>
<div class="search-bottom">
<div>
<span>状态span>
<el-select v-model="value" placeholder="状态">
<el-option
v-for="item in options2"
:key="item.value"
:label="item.label"
:value="item.value"
/>
el-select>
div>
<el-button :icon="Search" id="search" >搜索el-button>
<el-button :icon="Refresh" id="refresh">重置el-button>
<el-button :icon="Plus" id="plus">新增el-button>
div>
div>
<div class="main-content">
<el-table :data="member" style="width: 100%">
<el-table-column prop="id" label="会员ID" width="100" />
<el-table-column prop="icon" label="头像" width="200"/>
<el-table-column prop="memberName" label="名称" />
<el-table-column prop="phone" label="手机号" />
<el-table-column prop="residue" label="余额" />
<el-table-column prop="date" label="注册时间" />
<el-table-column prop="enable" label="状态" />
<el-table-column label="操作" />
el-table>
div>
div>
js部分
// 用于引入搜索,重置,添加几个图标,注意下面需要导出才能使用
import { Search, Refresh, Plus } from '@element-plus/icons-vue'
export default {
name: 'MemberLists',
data () {
return {
// 会员数据数组
member: [],
// 搜索框中两个下拉栏的数据
options1: [
{
value: '铜牌会员'
},
{
value: '白银会员'
},
{
value: '黄金会员'
},
{
value: '白金会员'
},
{
value: '钻石会员'
},
{
value: '黑卡会员'
}
],
options2: [
{
value: '启用'
},
{
value: '禁用'
}
],
input: null,
value: null
}
},
setup () {
return {
Search,
Refresh,
Plus
}
}
}
先写一个请求所有商品数据的请求,这里需要对应fastmock中的接口
// 单独管理memberList这个路由组件中所有请求
import request from '@/u/request'
// 请求所有商品数据
const fetchMemberLists = (params = {}) => {
return request.get('/memberLists', { params })
}
// 导出,函数方便复用,而且可以携带参数
export {
fetchMemberLists
}
回到MemberLists的index种引入请求方法fetchMemberLists,发送请求
// 引入发送请求,和数据更新的接口,在api的catelist中定义的
import { fetchMemberLists } from '@a/memberLists'
在methods中定义方法,发送数据请求
methods: {
// 请求会员所有数据
fetchMemberLists () {
fetchMemberLists({
}).then((result) => {
console.log(result)
})
}
}
这里可能会出现几个问题,打印结果为以下图片
原因可能是在vue.config.vue中的target没改变,写新的自己的接口,注意删除target最后的/api,因为下面重写了,不然这里在mock接口中还要写一次api,地址会拥有两个api,更改完config后一定要记得重启项目
实例创建时也就是created中就调用请求
created () {
this.fetchMemberLists()
}
mock接口中的数据
{
code: 200,
msg: "success",
data: {
"total|100-200": 100,
"lists|10": [
{
"id|+1": 1,
"memberName":"@cname",
icon:"https://api.vvhan.com/api/acgimg",
enable: "@Boolean",
date: "@date(yyyy-MM-dd hh:mm:ss)",
"phone":"@string(number,11)",
"residue|100-500":100,
"sort|10-200":10,
"children|3":[
{
"id|+1": 1,
enable:"@Boolean",
"memberName":"@cname",
icon:"https://api.vvhan.com/api/acgimg"
}
]
}
]
}
}
这里icon内部是一个随机图片的网址
此时效果渲染出来后发现图片未正常解析,按钮也没有,先解决图片解析的问题,进入el文档中,找到image一栏,这里有图片预览的相关操作,记得先在el-table-column中自定义列模版template,用来接收scope插槽传过来的值,row则是当前数据所有
<el-table-column prop="icon" label="头像" width="200">
<template #default="{ row }">
<el-image
style="width: 30px; height: 30px"
:src="row.icon"
:zoom-rate="1.2"
:preview-src-list="[row.icon]"
fit="cover"
preview-teleported
hide-on-click-modal
/>
template>
el-table-column>
完善表头样式
<el-table :data="member" style="width: 100%" :header-cell-style="{background:'rgb(245, 245, 245)'}" :cell-style="{'text-align':'center'}">
::v-deep .el-table__header-wrapper {
thead {
th{
div{
font-size: 12px;
color: #515a6e;
text-align: center;
}
}
}
}
效果如下
定义开关按钮,跟图片一样,先自定义列模版,获取所有数据,找到el-switch中对应的开关属性,这里绑定一个@change事件来使用参数开启和关闭
<el-table-column prop="enable" label="状态">
<template #default="{ row }">
<el-switch
v-model="row.enable"
inline-prompt
@change="switchCateState(row.id, row.enable)"
/>
template>
el-table-column>
在methods中定义该方法用于开关的开启和关闭未完善,后面需要在此处发送请求用于更新数据,而且需要弹出提示框dialog来确认是否删除
// 定义开关的方法,接收数据,id指定开关哪个和enable的布尔值
switchCateState (id, enable) {
// 行内修改分类显示隐藏图标,此时控制台可以打印出点击关闭开启对应的id和状态
console.log(id, enable)
}
操作删除和编辑,原理同上,这里要添加两个方法用于编辑和删除,传参就是row中对应的id,指定编辑和删除谁
<el-table-column label="操作">
<template #default="{ row }">
<div class="change-ope">
<el-icon :size="10" color="#ff6633"><EditPen />el-icon>
<span @click="showUpdatMemberDialog(row.id)" id="edit">编辑span>
<el-icon :size="10" color="#ff6633"><Delete />el-icon>
<span @click="delMember(row.id)">删除span>
div>
template>
el-table-column>
// 定义编辑按钮点击弹出框的方法
showUpdatMemberDialog () {
},
// 删除商品分类,接受参数id
delMember () {
}
添加列表分类下子分类,el中找到树形数据与懒加载,给el-table加row-key = “id"和:tree-prop定义是否有children,:tree-props=”{ children: ‘children’ }来实现,参考文档(这里我就不写了)
<el-button :icon="Search" id="search" @click="onSearch">搜索el-button>
el中找到分页效果Pagination,找到合适的样式cv过来,放在el-table中即可
<div class="demo-pagination-block">
<el-pagination
v-model:current-page="page"
v-model:page-size="pageSize"
:page-sizes="[10, 20, 30, 40]"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
/>
div>
data中定义分页的三个参数
// 分页的三个数据
page: 0,
pageSize: 10,
total: 0
在请求数据中fetchMemberLists加上页数的数据
// 请求会员所有数据
fetchMemberLists () {
fetchMemberLists({
// 展开运算符将data中的searchParams展开用于接收数据
...this.searchParams,
// 传递过来的参数就是data的page和pageSize
page: this.page,
pageSize: this.pageSize
}).then((result) => {
// console.log(result)
// 如果返回码为200
if (result.data.code === 200) {
// 空数组中填入数据返回结果中的lists
this.member = result.data.data.lists
// total为总条数,可以打印鉴别一下
this.total = result.data.data.total
console.log(result.data.data.total)
}
})
}
最后利用watch监听数据变化,也就是点击哪一页要重新发送请求
watch: {
// 数值只要改变的话就触发watch,重新发送请求,实现分页数据处理
page () {
this.fetchMemberLists()
},
pageSize () {
this.fetchMemberLists()
}
}
<el-dialog v-model="memberAddShow" title="添加分类" width="700">
<cate-add/>
el-dialog>