Vue + ElementUI的电商管理系统实例03 用户列表
1、通过路由展示用户列表页
新建user文件夹,里面新建Users.vue文件:
<template> <div> <h3>用户列表组件</h3> </div> </template> <script> export default { } </script> <style lang="less" scoped> </style>
修改路由文件,添加Users路由:
import Users from '../components/user/Users.vue' const routes = [ { path: '/', redirect: '/login' }, // 重定向 { path: '/login', component: Login }, { path: '/home', component: Home, redirect: '/welcome', // 重定向 children: [ // 子路由 { path: '/welcome', component: Welcome }, { path: '/users', component: Users } // 用户列表 ] } ]
这时点击左侧菜单的用户列表,就可以看到跳转到了用户列表页:
2、小bug:刷新后左侧菜单的高亮没有了
Menu Attribute里有个default-active属性: 表示当前激活菜单的 index,就是说如果想让菜单中的某一项高亮被激活,就把这项对应的index的值,赋值为整个menu菜单的default-active属性。
每次点击左侧二级菜单时,把对应的index的值,赋值给default-active属性。
<el-menu background-color="#333744" text-color="#fff" active-text-color="#409eff" :unique-opened="true" :collapse="isCollapse" :collapse-transition="false" :router="true" :default-active="activePath"> <el-menu-item :index="'/' + subItem.path" v-for="subItem in item.children" :key="subItem.id" @click="saveNavState"> <script> export default { data() { return { activePath: '' // 激活状态值 } }, methods: { // 保存菜单链接的激活状态 saveNavState(item) { console.log(item.index) this.activePath = item.index } } } </script>
这样写完后发现可以实现效果,但是一刷新,激活状态又没有了,,准备存到sessioStorage中实现保存:
<el-menu background-color="#333744" text-color="#fff" active-text-color="#409eff" :unique-opened="true" :collapse="isCollapse" :collapse-transition="false" :router="true" :default-active="activePath"> <el-menu-item :index="'/' + subItem.path" v-for="subItem in item.children" :key="subItem.id" @click="saveNavState"> <script> export default { data() { return { activePath: '' // 被激活的链接地址 } }, // 生命周期函数 created() { this.getMenuList() this.activePath = window.sessionStorage.getItem('activePath') }, methods: { // 保存菜单链接的激活状态 saveNavState(item) { console.log(item.index) this.activePath = item.index // 将点击之后的index地址保存到客户端的sessionStorage中 window.sessionStorage.setItem('activePath', item.index) } } } </script>
可以实现效果了,刷新后还是高亮的。
后来发现新版Element支持更简单的写法了:
<el-menu background-color="#333744" text-color="#fff" active-text-color="#409eff" :unique-opened="true" :collapse="isCollapse" :collapse-transition="false" :router="true" :default-active="$route.path"> <!--直接给default-active绑定$route.path的值就可以了-->
3、用户列表基础布局
首先要把使用的面包屑和卡片组件添加到element.js里:
import Vue from 'vue' import { Button, Form, FormItem, Input, Message, Container, Header, Aside, Main, Menu, Submenu, MenuItemGroup, MenuItem, Breadcrumb, BreadcrumbItem, Card } from 'element-ui' Vue.use(Button) Vue.use(Form) Vue.use(FormItem) Vue.use(Input) Vue.use(Container) Vue.use(Header) Vue.use(Aside) Vue.use(Main) Vue.use(Menu) Vue.use(Submenu) Vue.use(MenuItemGroup) Vue.use(MenuItem) Vue.use(Breadcrumb) Vue.use(BreadcrumbItem) Vue.use(Card) // 挂载到Vue全局 Vue.prototype.$message = Message
在Users.vue里添加面包屑和卡片代码:
<template> <div> <!--面包屑导航区域--> <el-breadcrumb separator-class="el-icon-arrow-right"> <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item> <el-breadcrumb-item>用户管理</el-breadcrumb-item> <el-breadcrumb-item>用户列表</el-breadcrumb-item> </el-breadcrumb> <!--卡片视图区域--> <el-card> 111 </el-card> </div> </template>
然后在全局样式global里添加重置样式:
/* 全局样式表 */ html, body, #app {height: 100%; margin: 0; padding: 0;} .el-breadcrumb{margin-bottom: 15px;font-size: 12px;} .el-card{box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1) !important;}
然后进行卡片里的布局,上部是一个搜索框和一个添加按钮,这个可以用栅格布局,记得把Row, Col添加导入到element.js,这里就不写了
实现代码:
<template> <div> <!--面包屑导航区域--> <el-breadcrumb separator-class="el-icon-arrow-right"> <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item> <el-breadcrumb-item>用户管理</el-breadcrumb-item> <el-breadcrumb-item>用户列表</el-breadcrumb-item> </el-breadcrumb> <!--卡片视图区域--> <el-card> <el-row :gutter="20"> <el-col :span="10"> <!--搜索区域--> <el-input placeholder="请输入内容"> <el-button slot="append" icon="el-icon-search"></el-button> </el-input> </el-col> <el-col :span="4"> <el-button type="primary">添加用户</el-button> </el-col> </el-row> </el-card> </div> </template>
实现效果:
4、请求接口获取用户列表数据
查看接口文档,1.3.1用户数据列表:请求路径是users,请求方式是get,请求参数是:query 查询参数 可以为空、pagenum 当前页码 不能为空、pagesize 每页显示条数 不能为空
代码如下:
<script> export default { data() { return { userList: [], // 用户列表 total: 0, // 用户总数 // 获取用户列表的参数对象 queryInfo: { query: '', // 查询参数 pagenum: 1, // 当前页码 pagesize: 2 // 每页显示条数 } } }, created() { // 生命周期函数 this.getUserList() }, methods: { async getUserList() { const { data: res } = await this.$http.get('users', { params: this.queryInfo }) console.log(res) if (res.meta.status !== 200) return this.$message.error(res.meta.msg) this.userList = res.data.users this.total = res.data.total } } } </script>
5、使用表格组件渲染用户列表
首先还是在element.js里添加Table和TableColumn导入:
import Vue from 'vue' import { Button, Form, FormItem, Input, Message, Container, Header, Aside, Main, Menu, Submenu, MenuItemGroup, MenuItem, Breadcrumb, BreadcrumbItem, Card, Row, Col, Table, TableColumn } from 'element-ui' Vue.use(Button) Vue.use(Form) Vue.use(FormItem) Vue.use(Input) Vue.use(Container) Vue.use(Header) Vue.use(Aside) Vue.use(Main) Vue.use(Menu) Vue.use(Submenu) Vue.use(MenuItemGroup) Vue.use(MenuItem) Vue.use(Breadcrumb) Vue.use(BreadcrumbItem) Vue.use(Card) Vue.use(Row) Vue.use(Col) Vue.use(Table) Vue.use(TableColumn) // 挂载到Vue全局 Vue.prototype.$message = Message
然后添加代码:
<!--用户列表区域--> <el-table :data="userList" style="width: 100%" border stripe> <el-table-column prop="username" label="姓名"></el-table-column> <el-table-column prop="email" label="邮箱"></el-table-column> <el-table-column prop="mobile" label="电话"></el-table-column> <el-table-column prop="role_name" label="角色"></el-table-column> <el-table-column prop="mg_state" label="状态"></el-table-column> <el-table-column label="操作"></el-table-column> </el-table>
边框:默认情况下,Table 组件是不具有竖直方向的边框的,如果需要,可以使用border
属性,它接受一个Boolean
,设置为true
即可启用。
隔行变色:stripe
属性可以创建带斑马纹的表格。它接受一个Boolean
,默认为false
,设置为true
即为启用。
6、表格前面添加索引列
type="index"
<!--用户列表区域--> <el-table :data="userList" style="width: 100%" border stripe> <el-table-column type="index" label="#"></el-table-column> <el-table-column prop="username" label="姓名"></el-table-column> <el-table-column prop="email" label="邮箱"></el-table-column> <el-table-column prop="mobile" label="电话"></el-table-column> <el-table-column prop="role_name" label="角色"></el-table-column> <el-table-column prop="mg_state" label="状态"></el-table-column> <el-table-column label="操作"></el-table-column> </el-table>
效果图:
7、自定义状态列的显示效果
用到Switch 开关组件,添加导入到element.js,这里就不写了。
然后要用到作用域插槽:
<!-- 作用域插槽 --> <template slot-scope="scope"> {{scope.row}} </template>
这里定义了一个作用域插槽,通过slot-scope="scope"接收了当前作用域的数据,然后通过scope.row拿到对应这一行的数据,再绑定具体的属性值就行了。
<el-table-column prop="mg_state" label="状态"> <!-- 作用域插槽 --> <template slot-scope="scope"> <!-- {{scope.row}} --> <el-switch v-model="scope.row.mg_state"></el-switch> </template> </el-table-column>
如果同时指定了prop和作用域插槽,那么作用域插槽会覆盖prop,所以prop就不生效了,可以删掉。
8、通过作用域插槽自定义操作列
要用过id来操作对应数据,还是定义作用域插槽来实现:
<el-table-column label="操作"> <!-- 作用域插槽 --> <template slot-scope="scope"> {{scope.row.id}} </template> </el-table-column>
然后要添加三个按钮组件: size表示尺寸
<!--修改--> <el-button type="primary" size="mini" icon="el-icon-edit"></el-button> <!--删除--> <el-button type="danger" size="mini" icon="el-icon-delete"></el-button> <!--分配角色--> <el-button type="warning" size="mini" icon="el-icon-setting"></el-button>
需要给分配角色按钮添加一个鼠标移上去有提示信息,使用Tooltip 文字提示组件,添加导入这里就不写了:
<!--分配角色--> <el-tooltip class="item" effect="dark" content="分配角色" placement="top" :enterable="false"> <el-button type="warning" size="mini" icon="el-icon-setting"></el-button> </el-tooltip>
enterable属性:表示鼠标是否可进入到 tooltip 中,默认是true开的,需要把它绑定为false,鼠标移到上面提示就消失了。
效果图:
9、实现分页效果
Pagination 分页组件,添加导入这里就不写了
属性参数 说明 类型 可选值 默认值
current-page 当前页数,支持 .sync 修饰符 number — 1
page-sizes 每页显示个数选择器的选项设置 number[] — [10, 20, 30, 40, 50, 100]
page-size 每页显示条目个数,支持 .sync 修饰符 number — 10
total 总条目数 number — —
layout 组件布局,子组件名用逗号分隔 String sizes, prev, pager, next, jumper, ->, total, slot 'prev, pager, next, jumper, ->, total'
事件名称 说明 回调参数
size-change pageSize改变时会触发 每页条数
current-change currentPage改变时会触发 当前页
prev-click 用户点击上一页按钮改变当前页后触发 当前页
next-click 用户点击下一页按钮改变当前页后触发 当前页
<!--分页区域--> <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="queryInfo.pagenum" :page-sizes="[1, 2, 5, 10]" :page-size="queryInfo.pagesize" layout="total, sizes, prev, pager, next, jumper" :total="total"> </el-pagination> <script> export default { methods: { // 监听 pageSize 改变的事件 handleSizeChange(newSize) { console.log(newSize) }, // 监听 当前页码值 改变的事件 handleCurrentChange(newPage) { console.log(newPage) } } } </script>
然后把点击改变后的newSize和newPage,再赋值给回pagesize和pagenum,然后重新获取用户列表数据:
// 监听 pageSize 改变的事件 handleSizeChange(newSize) { // console.log(newSize) this.queryInfo.pagesize = newSize // 重新发起请求用户列表 this.getUserList() }, // 监听 当前页码值 改变的事件 handleCurrentChange(newPage) { // console.log(newPage) this.queryInfo.pagenum = newPage // 重新发起请求用户列表 this.getUserList() }
在添加一个全局的分页样式:
/* 全局样式表 */ html, body, #app {height: 100%; margin: 0; padding: 0;} .el-breadcrumb{margin-bottom: 15px;font-size: 12px;} .el-card{box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1) !important;} .el-table{margin-top: 15px;font-size: 12px;} .el-pagination{margin-top: 15px;}
现在点击分页,用户列表数据就可以随之变化了。
效果图:
10、修改用户状态
查看Switch事件:
事件名称 说明 回调参数
change switch 状态发生变化时的回调函数 新状态的值
修改代码,添加事件:
<el-table-column label="状态"> <!-- 作用域插槽 --> <template slot-scope="scope"> <el-switch v-model="scope.row.mg_state" @change="userStateChanged(scope.row)"></el-switch> </template> </el-table-column> <script> export default { methods: { // 监听 当前状态值 改变事件 userStateChanged(userinfo) { console.log(userinfo) } } } </script>
现在就要把修改后的用户信息保存到服务器。
查看接口文档,1.3.3. 修改用户状态,请求路径:users/:uId/state/:type,请求方法:put,
请求参数:uId:用户ID:不能为空`携带在url中、type:用户状态:不能为空`携带在url中`:值为 true 或者 false
修改添加代码:
// 监听 当前状态值 改变事件 async userStateChanged(userinfo) { console.log(userinfo) const { data: res } = await this.$http.put( `users/${userinfo.id}/state/${userinfo.mg_state}` ) if (res.meta.status !== 200) { userinfo.ms_state = !userinfo.ms_state return this.$message.error('更新用户状态失败') } this.$message.success('更新用户状态成功!') } // 注意put这里为了拼接动态参数用的是反引号``
现在点击修改用户状态,再重新刷新后,显示的还是刚才修改后的状态,成功。
11、实现搜索功能
给搜索框实现双向绑定,并添加点击事件:绑定queryInfo.query,点击重新获取用户列表
<!--搜索区域--> <el-input v-model="queryInfo.query" placeholder="请输入内容"> <el-button slot="append" icon="el-icon-search" @click="getUserList"></el-button> </el-input>
添加清空按钮,清空输入框同时刷新用户列表:
使用clearable
属性即可得到一个可清空的输入框
clear事件 在点击由 clearable 属性生成的清空按钮时触发
<el-input v-model="queryInfo.query" placeholder="请输入内容" clearable @clear="getUserList">
效果图: