打開Home.vue組件,進行布局:
<el-container class="home-container">
<!-- 頭部區(qū)域 -->
<el-header>Header<el-button type="info" @click="logout"> 退出 </el-button></el-header>
<!-- 頁面主體區(qū)域 -->
<el-container>
<!-- 側邊欄 -->
<el-aside width="200px">Aside</el-aside>
<!-- 主體結構 -->
<el-main>Main</el-main>
</el-container>
</el-container>
默認情況下,跟element-ui組件同名的類名可以幫助我們快速的給對應的組件添加樣式,如:
.home-container {
height: 100%;
}
.el-header{
background-color:#373D41;
}
.el-aside{
background-color:#333744;
}
.el-main{
background-color:#eaedf1;
}
2.頂部布局,側邊欄布局
<template>
<el-container class="home-container">
<!-- 頭部區(qū)域 -->
<el-header>
<div>
<!-- 黑馬logo -->
<img src="../assets/heima.png" alt="">
<!-- 頂部標題 -->
<span>電商后臺管理系統(tǒng)</span>
</div>
<el-button type="info" @click="logout"> 退出 </el-button>
</el-header>
<!-- 頁面主體區(qū)域 -->
<el-container>
<!-- 側邊欄 -->
<el-aside width="200px">
<!-- 側邊欄菜單 -->
<el-menu
background-color="#333744"
text-color="#fff"
active-text-color="#ffd04b">
<!-- 一級菜單 -->
<el-submenu index="1">
<!-- 一級菜單模板 -->
<template slot="title">
<!-- 圖標 -->
<i class="el-icon-location"></i>
<!-- 文本 -->
<span>導航一</span>
</template>
<!-- 二級子菜單 -->
<el-menu-item index="1-4-1">
<!-- 二級菜單模板 -->
<template slot="title">
<!-- 圖標 -->
<i class="el-icon-location"></i>
<!-- 文本 -->
<span>子菜單一</span>
</template>
</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
<!-- 主體結構 -->
<el-main>Main</el-main>
</el-container>
</el-container>
</template>
3.axios請求攔截器
后臺除了登錄接口之外,都需要token權限驗證,我們可以通過添加axios請求攔截器來添加token,以保證擁有獲取數(shù)據(jù)的權限
在main.js中添加代碼,在將axios掛載到vue原型之前添加下面的代碼
//請求在到達服務器之前,先會調(diào)用use中的這個回調(diào)函數(shù)來添加請求頭信息
axios.interceptors.request.use(config=>{
//為請求頭對象,添加token驗證的Authorization字段
config.headers.Authorization = window.sessionStorage.getItem("token")
return config
})
4.請求側邊欄數(shù)據(jù)
<script>
export default {
data() {
return {
// 左側菜單數(shù)據(jù)
menuList: null
}
},
created() {
// 在created階段請求左側菜單數(shù)據(jù)
this.getMenuList()
},
methods: {
logout() {
window.sessionStorage.clear()
this.$router.push('/login')
},
async getMenuList() {
// 發(fā)送請求獲取左側菜單數(shù)據(jù)
const { data: res } = await this.$http.get('menus')
if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
this.menuList = res.data
console.log(res)
}
}
}
</script>
通過v-for雙重循環(huán)渲染左側菜單
<el-menu
background-color="#333744"
text-color="#fff"
active-text-color="#ffd04b">
<!-- 一級菜單 -->
<el-submenu :index="item.id+''" v-for="item in menuList" :key="item.id">
<!-- 一級菜單模板 -->
<template slot="title">
<!-- 圖標 -->
<i class="el-icon-location"></i>
<!-- 文本 -->
<span>{{item.authName}}</span>
</template>
<!-- 二級子菜單 -->
<el-menu-item :index="subItem.id+''" v-for="subItem in item.children" :key="subItem.id">
<!-- 二級菜單模板 -->
<template slot="title">
<!-- 圖標 -->
<i class="el-icon-location"></i>
<!-- 文本 -->
<span>{{subItem.authName}}</span>
</template>
</el-menu-item>
</el-submenu>
</el-menu>
5.設置激活子菜單樣式
通過更改el-menu的active-text-color屬性可以設置側邊欄菜單中點擊的激活項的文字顏色
通過更改菜單項模板(template)中的i標簽的類名,可以將左側菜單欄的圖標進行設置,我們需要在項目中使用第三方字體圖標
在數(shù)據(jù)中添加一個iconsObj:
iconsObj: {
'125':'iconfont icon-user',
'103':'iconfont icon-tijikongjian',
'101':'iconfont icon-shangpin',
'102':'iconfont icon-danju',
'145':'iconfont icon-baobiao'
}
然后將圖標類名進行數(shù)據(jù)綁定,綁定iconsObj中的數(shù)據(jù):
為了保持左側菜單每次只能打開一個,顯示其中的子菜單,我們可以在el-menu中添加一個屬性unique-opened
或者也可以數(shù)據(jù)綁定進行設置(此時true認為是一個bool值,而不是字符串) :unique-opened="true"
6.制作側邊菜單欄的伸縮功能
在菜單欄上方添加一個div
<!-- 側邊欄,寬度根據(jù)是否折疊進行設置 -->
<el-aside :width="isCollapse ? '64px':'200px'">
<!-- 伸縮側邊欄按鈕 -->
<div class="toggle-button" @click="toggleCollapse">|||</div>
<!-- 側邊欄菜單,:collapse="isCollapse"(設置折疊菜單為綁定的 isCollapse 值),:collapse-transition="false"(關閉默認的折疊動畫) -->
<el-menu
:collapse="isCollapse"
:collapse-transition="false"
......
然后給div添加樣式,給div添加事件:
<div class="toggle-button" @click="this.isCollapse ? '64px':'200px'">|||</div>
7.在后臺首頁添加子級路由
新增子級路由組件Welcome.vue
在router.js中導入子級路由組件,并設置路由規(guī)則以及子級路由的默認重定向
打開Home.vue,在main的主體結構中添加一個路由占位符
制作好了Welcome子級路由之后,我們需要將所有的側邊欄二級菜單都改造成子級路由鏈接
我們只需要將el-menu的router屬性設置為true就可以了,此時當我們點擊二級菜單的時候,就會根據(jù)菜單的index
屬性進行路由跳轉,如: /110,
使用index id來作為跳轉的路徑不合適,我們可以重新綁定index的值為 :index="'/'+subItem.path"
子路由的寫法
{
path: '/home',
component: Home,
redirect: '/welcome',
children: [
{ path: '/welcome', component: Welcome },
{ path: '/users', component: Users }
]
}
8.完成用戶列表主體區(qū)域
新建用戶列表組件 user/Users.vue
在router.js中導入子級路由組件Users.vue,并設置路由規(guī)則
當點擊二級菜單的時候,被點擊的二級子菜單并沒有高亮,我們需要正在被使用的功能高亮顯示
我們可以通過設置el-menu的default-active屬性來設置當前激活菜單的index
但是default-active屬性也不能寫死,固定為某個菜單值
所以我們可以先給所有的二級菜單添加點擊事件,并將path值作為方法的參數(shù)
@click="saveNavState('/'+subItem.path)"
在saveNavState方法中將path保存到sessionStorage中
saveNavState( path ){
//點擊二級菜單的時候保存被點擊的二級菜單信息
window.sessionStorage.setItem("activePath",path);
this.activePath = path;
}
然后在數(shù)據(jù)中添加一個activePath綁定數(shù)據(jù),并將el-menu的default-active屬性設置為activePath
最后在created中將sessionStorage中的數(shù)據(jù)賦值給activePath
this.activePath = window.sessionStorage.getItem("activePath")
9.繪制用戶列表基本結構
A.使用element-ui面包屑組件完成頂部導航路徑(復制面包屑代碼,在element.js中導入組件Breadcrumb,BreadcrumbItem)
B.使用element-ui卡片組件完成主體表格(復制卡片組件代碼,在element.js中導入組件Card),再使用element-ui輸入框完成搜索框及搜索按鈕,
此時我們需要使用柵格布局來劃分結構(復制卡片組件代碼,在element.js中導入組件Row,Col),然后再使用el-button制作添加用戶按鈕
<div>
<h3>用戶列表組件</h3>
<!-- 面包屑導航 -->
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/home' }">首頁</el-breadcrumb-item>
<el-breadcrumb-item>用戶管理</el-breadcrumb-item>
<el-breadcrumb-item>用戶列表</el-breadcrumb-item>
</el-breadcrumb>
<!-- 卡片視圖區(qū)域 -->
<el-card>
<!-- 搜索與添加區(qū)域 -->
<el-row :gutter="20">
<el-col :span="7">
<el-input placeholder="請輸入內(nèi)容">
<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>
10.請求用戶列表數(shù)據(jù)
<script>
export default {
data() {
return {
//獲取查詢用戶信息的參數(shù)
queryInfo: {
query: '',
pagenum: 1,
pagesize: 2
},
//保存請求回來的用戶列表數(shù)據(jù)
userList:[],
total:0
}
},
created() {
this.getUserList()
},
methods: {
async getUserList() {
//發(fā)送請求獲取用戶列表數(shù)據(jù)
const { res: data } = await this.$http.get('users', {
params: this.queryInfo
})
//如果返回狀態(tài)為異常狀態(tài)則報錯并返回
if (res.meta.status !== 200)
return this.$message.error('獲取用戶列表失敗')
//如果返回狀態(tài)正常,將請求的數(shù)據(jù)保存在data中
this.userList = res.data.users;
this.total = res.data.total;
}
}
}
</script>
11.將用戶列表數(shù)據(jù)展示
使用表格來展示用戶列表數(shù)據(jù),使用element-ui表格組件完成列表展示數(shù)據(jù)(復制表格代碼,在element.js中導入組件Table,TableColumn)
在渲染展示狀態(tài)時,會使用作用域插槽獲取每一行的數(shù)據(jù)
再使用switch開關組件展示狀態(tài)信息(復制開關組件代碼,在element.js中導入組件Switch)
而渲染操作列時,也是使用作用域插槽來進行渲染的,
在操作列中包含了修改,刪除,分配角色按鈕,當我們把鼠標放到分配角色按鈕上時
希望能有一些文字提示,此時我們需要使用文字提示組件(復制文字提示組件代碼,在element.js中導入組件Tooltip),將分配角色按鈕包含
代碼結構如下:
<!-- 用戶列表(表格)區(qū)域 -->
<el-table :data="userList" border stripe>
<el-table-column type="index"></el-table-column>
<el-table-column label="姓名" prop="username"></el-table-column>
<el-table-column label="郵箱" prop="email"></el-table-column>
<el-table-column label="電話" prop="mobile"></el-table-column>
<el-table-column label="角色" prop="role_name"></el-table-column>
<el-table-column label="狀態(tài)">
<template slot-scope="scope">
<el-switch v-model="scope.row.mg_state"></el-switch>
</template>
</el-table-column>
<el-table-column label="操作" width="180px">
<template slot-scope="scope">
<!-- 修改 -->
<el-button type="primary" icon="el-icon-edit" size='mini'></el-button>
<!-- 刪除 -->
<el-button type="danger" icon="el-icon-delete" size='mini'></el-button>
<!-- 分配角色 -->
<el-tooltip class="item" effect="dark" content="分配角色" placement="top" :enterable="false">
<el-button type="warning" icon="el-icon-setting" size='mini'></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
12.實現(xiàn)用戶列表分頁
A.使用表格來展示用戶列表數(shù)據(jù),可以使用分頁組件完成列表分頁展示數(shù)據(jù)(復制分頁組件代碼,在element.js中導入組件Pagination)
B.更改組件中的綁定數(shù)據(jù)
<!-- 分頁導航區(qū)域
@size-change(pagesize改變時觸發(fā))
@current-change(頁碼發(fā)生改變時觸發(fā))
:current-page(設置當前頁碼)
:page-size(設置每頁的數(shù)據(jù)條數(shù))
:total(設置總頁數(shù)) -->
<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>
C.添加兩個事件的事件處理函數(shù)@size-change,@current-change
handleSizeChange(newSize) {
//pagesize改變時觸發(fā),當pagesize發(fā)生改變的時候,我們應該
//以最新的pagesize來請求數(shù)據(jù)并展示數(shù)據(jù)
// console.log(newSize)
this.queryInfo.pagesize = newSize;
//重新按照pagesize發(fā)送請求,請求最新的數(shù)據(jù)
this.getUserList();
},
handleCurrentChange( current ) {
//頁碼發(fā)生改變時觸發(fā)當current發(fā)生改變的時候,我們應該
//以最新的current頁碼來請求數(shù)據(jù)并展示數(shù)據(jù)
// console.log(current)
this.queryInfo.pagenum = current;
//重新按照pagenum發(fā)送請求,請求最新的數(shù)據(jù)
this.getUserList();
}
13.實現(xiàn)更新用戶狀態(tài)
當用戶點擊列表中的switch組件時,用戶的狀態(tài)應該跟隨發(fā)生改變。
A.首先監(jiān)聽用戶點擊switch組件的事件,并將作用域插槽的數(shù)據(jù)當做事件參數(shù)進行傳遞
<el-switch v-model="scope.row.mg_state" @change="userStateChanged(scope.row)"></el-switch>
B.在事件中發(fā)送請求完成狀態(tài)的更改
async userStateChanged(row) {
//發(fā)送請求進行狀態(tài)修改
const { data: res } = await this.$http.put(
`users/${row.id}/state/${row.mg_state}`
)
//如果返回狀態(tài)為異常狀態(tài)則報錯并返回
if (res.meta.status !== 200) {
row.mg_state = !row.mg_state
return this.$message.error('修改狀態(tài)失敗')
}
this.$message.success('更新狀態(tài)成功')
},
14.實現(xiàn)搜索功能
添加數(shù)據(jù)綁定,添加搜索按鈕的點擊事件(當用戶點擊搜索按鈕的時候,調(diào)用getUserList方法根據(jù)文本框內(nèi)容重新請求用戶列表數(shù)據(jù))
當我們在輸入框中輸入內(nèi)容并點擊搜索之后,會按照搜索關鍵字搜索,我們希望能夠提供一個X刪除搜索關鍵字并重新獲取所有的用戶列表數(shù)據(jù),只需要給文本框添加clearable屬性并添加clear事件,在clear事件中重新請求數(shù)據(jù)即可
<el-col :span="7">
<el-input placeholder="請輸入內(nèi)容" v-model="queryInfo.query" clearable @clear="getUserList">
<el-button slot="append" icon="el-icon-search" @click="getUserList"></el-button>
</el-input>
</el-col>
15.實現(xiàn)添加用戶
A.當我們點擊添加用戶按鈕的時候,彈出一個對話框來實現(xiàn)添加用戶的功能,首先我們需要復制對話框組件的代碼并在element.js文件中引入Dialog組件
B.接下來我們要為“添加用戶”按鈕添加點擊事件,在事件中將addDialogVisible設置為true,即顯示對話框
C.更改Dialog組件中的內(nèi)容
<!-- 對話框組件 :visible.sync(設置是否顯示對話框) width(設置對話框的寬度)
:before-close(在對話框關閉前觸發(fā)的事件) -->
<el-dialog title="添加用戶" :visible.sync="addDialogVisible" width="50%">
<!-- 對話框主體區(qū)域 -->
<el-form :model="addForm" :rules="addFormRules" ref="addFormRef" label-width="70px">
<el-form-item label="用戶名" prop="username">
<el-input v-model="addForm.username"></el-input>
</el-form-item>
<el-form-item label="密碼" prop="password">
<el-input v-model="addForm.password"></el-input>
</el-form-item>
<el-form-item label="郵箱" prop="email">
<el-input v-model="addForm.email"></el-input>
</el-form-item>
<el-form-item label="電話" prop="mobile">
<el-input v-model="addForm.mobile"></el-input>
</el-form-item>
</el-form>
<!-- 對話框底部區(qū)域 -->
<span slot="footer" class="dialog-footer">
<el-button @click="addDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="addDialogVisible = false">確 定</el-button>
</span>
</el-dialog>
D.添加數(shù)據(jù)綁定和校驗規(guī)則:
data() {
//驗證郵箱的規(guī)則
var checkEmail = (rule, value, cb) => {
const regEmail = /^\w+@\w+(\.\w+)+$/
if (regEmail.test(value)) {
return cb()
}
//返回一個錯誤提示
cb(new Error('請輸入合法的郵箱'))
}
//驗證手機號碼的規(guī)則
var checkMobile = (rule, value, cb) => {
const regMobile = /^1[34578]\d{9}$/
if (regMobile.test(value)) {
return cb()
}
//返回一個錯誤提示
cb(new Error('請輸入合法的手機號碼'))
}
return {
//獲取查詢用戶信息的參數(shù)
queryInfo: {
// 查詢的條件
query: '',
// 當前的頁數(shù),即頁碼
pagenum: 1,
// 每頁顯示的數(shù)據(jù)條數(shù)
pagesize: 2
},
//保存請求回來的用戶列表數(shù)據(jù)
userList: [],
total: 0,
//是否顯示添加用戶彈出窗
addDialogVisible: false,
// 添加用戶的表單數(shù)據(jù)
addForm: {
username: '',
password: '',
email: '',
mobile: ''
},
// 添加表單的驗證規(guī)則對象
addFormRules: {
username: [
{ required: true, message: '請輸入用戶名稱', trigger: 'blur' },
{
min: 3,
max: 10,
message: '用戶名在3~10個字符之間',
trigger: 'blur'
}
],
password: [
{ required: true, message: '請輸入密碼', trigger: 'blur' },
{
min: 6,
max: 15,
message: '用戶名在6~15個字符之間',
trigger: 'blur'
}
],
email: [
{ required: true, message: '請輸入郵箱', trigger: 'blur' },
{ validator:checkEmail, message: '郵箱格式不正確,請重新輸入', trigger: 'blur'}
],
mobile: [
{ required: true, message: '請輸入手機號碼', trigger: 'blur' },
{ validator:checkMobile, message: '手機號碼不正確,請重新輸入', trigger: 'blur'}
]
}
}
}
E.當關閉對話框時,重置表單
給el-dialog添加@close事件,在事件中添加重置表單的代碼
methods:{
....
addDialogClosed(){
//對話框關閉之后,重置表達
this.$refs.addFormRef.resetFields();
}
}
F.點擊對話框中的確定按鈕,發(fā)送請求完成添加用戶的操作
首先給確定按鈕添加點擊事件,在點擊事件中完成業(yè)務邏輯代碼
methods:{
....
addUser(){
//點擊確定按鈕,添加新用戶
//調(diào)用validate進行表單驗證
this.$refs.addFormRef.validate( async valid => {
if(!valid) return this.$message.error("請?zhí)顚懲暾脩粜畔?);
//發(fā)送請求完成添加用戶的操作
const {data:res} = await this.$http.post("users",this.addForm)
//判斷如果添加失敗,就做提示
if (res.meta.status !== 200)
return this.$message.error('添加用戶失敗')
//添加成功的提示
this.$message.success("添加用戶成功")
//關閉對話框
this.addDialogVisible = false
//重新請求最新的數(shù)據(jù)
this.getUserList()
})
}
}