用戶列表頁實(shí)現(xiàn)
1.完成user組件靜態(tài)布局
頁面結(jié)構(gòu):組件盒子內(nèi)分五部分颠区,頂級面包屑(全局組件)+ 操作框 + 用戶數(shù)據(jù)列表 + 底部的分頁 + 用戶增刪改彈框(后面寫動(dòng)態(tài)交互再添加)硫眨,都用el-row(餓了嗎Layout 布局)包裹
Ⅰ.頂級面包屑的實(shí)現(xiàn):參照前兩章
Ⅱ.操縱框:
餓了嗎組件 復(fù)合型輸入框傳送們http://element-cn.eleme.io/#/zh-CN/component/input
???button按鈕 傳送門http://element-cn.eleme.io/#/zh-CN/component/button
Ⅲ.用戶數(shù)據(jù)列表:
餓了嗎組件 Table表格(固定列表格) 傳送門http://element-cn.eleme.io/#/zh-CN/component/table
???Switch 開關(guān)傳送門http://element-cn.eleme.io/#/zh-CN/component/switch
Ⅳ.底部的分頁:
餓了嗎組件 Pagination 分頁(完整功能)傳送門http://element-cn.eleme.io/#/zh-CN/component/pagination
示例代碼
<template>
<div id="user">
<!-- 頂級面包屑 -->
<el-row>
<el-col :span="24">
<breadcrumb :level2="level2" :level3="level3"></breadcrumb>
</el-col>
</el-row>
<!-- 操縱框 -->
<el-row class="operate">
<el-col :span="4">
<!-- 輸入的內(nèi)容最終是放在搜索里面 -->
<el-input placeholder="請輸入內(nèi)容" v-model="pageData.query">
<template slot="append">
<i class="el-icon-search"></i>
</template>
</el-input>
</el-col>
<el-col :span="20">
<el-button type="success" plain>添加用戶</el-button>
</el-col>
</el-row>
<!-- 用戶數(shù)據(jù) -->
<el-row>
<el-col :sapn="24">
<el-table :data="userList" style="width: 100%" border>
<!-- 返回的數(shù)據(jù)沒有對應(yīng)的屬性名,把prop刪掉 -->
<!-- 增加type="index"桂敛,會設(shè)置排序 -->
<el-table-column label="#" width="30" type="index"></el-table-column>
<el-table-column prop="username" label="姓名" width="180"></el-table-column>
<el-table-column prop="email" label="郵箱" width="300"></el-table-column>
<el-table-column prop="mobile" label="電話" width="300"></el-table-column>
<el-table-column prop="mg_state" label="用戶狀態(tài)" width="80">
<!-- slot-scope 廢棄怠李,已經(jīng)被v-slot代替针姿,為插槽傳入 prop 的時(shí)候使用 -->
<template slot-scope="scope">
<el-switch
v-model="scope.row.mg_state"
active-color="#13ce66"
inactive-color="#ff4949"
></el-switch>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="primary" plain size="mini" icon="el-icon-edit"></el-button>
<el-button type="danger" plain size="mini" icon="el-icon-check"></el-button>
<el-button type="warning" plain size="mini" icon="el-icon-delete"></el-button>
</template>
</el-table-column>
</el-table>
</el-col>
</el-row>
<!-- 底部的分頁 -->
<el-row>
<el-col :span="24">
<!-- 刪掉el-pagination如下的默認(rèn)事件 -->
<!-- @size-change="handleSizeChange"
@current-change="handleCurrentChange" -->
<el-pagination
:current-page="pageData.pagenum"
:page-sizes="[2, 4, 6, 8, 10]"
:page-size="pageData.pagesize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
data() {
return {
level2: "用戶管理",
level3: "用戶列表",
//頁碼
pageData: {
pagenum: 1,
pagesize: 10,
query: ""
},
//總頁數(shù),默認(rèn)為0
total: 0,
//用戶的數(shù)據(jù)
userList: []
};
},
created() {
//get請求需要通過params屬性來傳對象
this.$axios.get("users", { params: this.pageData }).then(res => {
console.log(res);
this.userList = res.data.data.users;
this.total = res.data.data.total;
});
}
};
</script>
<style lang="scss">
#user {
.operate {
background-color: #e8edf3;
}
}
</style>
2.完成user組件動(dòng)態(tài)交互
Ⅰ.用戶查詢
NO. | 題外話:組件中寫name的好處 |
---|---|
1 | vue開發(fā)者界面語義更明確 |
2 | 可以使用搜索快速定位到組件 |
用戶查詢步驟:點(diǎn)搜索→發(fā)請求→調(diào)接口→拿數(shù)據(jù)
NO. | 用戶查詢步驟 |
---|---|
1 | 根據(jù)input輸入的查詢字段可以進(jìn)行模糊搜索乒省,如果input輸入為空默認(rèn)搜索到全部用戶 |
2 | 搜索方法和頁面刷新created調(diào)用的方法一樣,可以封裝復(fù)用 |
Ⅱ.用戶添加
餓了嗎:Dialog 對話框(自定義內(nèi)容) 傳送門http://element-cn.eleme.io/#/zh-CN/component/dialog
NO. | Dialog對話框 |
---|---|
1 | 和面包屑同級钝满,新增html用戶添加的對話框代碼 |
1 | 在form上添加:rules="rules"屬性兜粘,增加表單數(shù)據(jù)驗(yàn)證 |
2 | 在form上添加:ref="userForm"屬性,并將userForm傳給提交按鈕弯蚜,增加表單提交驗(yàn)證 |
3 | 表單驗(yàn)證是前端驗(yàn)證可以被繞過妹沙,主要防止普通用戶的誤操作 |
4 | 技術(shù)用戶可以繞過前端驗(yàn)證,比如用postman直接發(fā)送請求熟吏,添加用戶,就不需要受到前端的限制 |
5 | 所以后端服務(wù)器一定會再驗(yàn)證一次 |
//template
<!-- 添加用戶的對話框 -->
<el-dialog title="添加用戶" :visible.sync="visible">
<!-- label-position控制label名的顯示位置玄窝,注意要設(shè)置label-width才能生效 -->
<!-- 表單數(shù)據(jù)驗(yàn)證要加form上添加:rules="rules"屬性 -->
<!-- 表單提交驗(yàn)證要加ref="userForm"屬性,并將userForm傳給提交按鈕 -->
<el-form :model="form" :rules="rules" ref="userForm" label-position="left" label-width="70px">
<el-form-item label="用戶名" prop="username">
<el-input v-model="form.username" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="密碼" prop="password">
<!-- 添加type="password"屬性牵寺,讓密碼不明文顯示 -->
<el-input v-model="form.password" type="password" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="郵箱">
<el-input v-model="form.email" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="手機(jī)號">
<el-input v-model="form.mobile" autocomplete="off"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="visible = false">取 消</el-button>
<!-- 記住這邊的userForm要加單引號 -->
<el-button type="primary" @click="submitForm('userForm')">確 定</el-button>
</div>
</el-dialog>
//css
<style lang="scss">
#user {
.operate {
background-color: #e8edf3;
}
.el-dialog {
width:30%;
}
}
</style>
//js
<script>
export default {
//寫了name方便在Vue Devtools谷歌插件應(yīng)用內(nèi)找到對應(yīng)的組件
name: "user",
data() {
return {
level2: "用戶管理",
level3: "用戶列表",
//頁碼
pageData: {
pagenum: 1,
pagesize: 10,
//query是查詢的字段
query: ""
},
//總頁數(shù),默認(rèn)為0
total: 0,
//用戶的數(shù)據(jù)
userList: [],
//是否 顯示對話框
visible: false,
form: {
username: "",
password: "",
email: "",
mobile: ""
},
//表單驗(yàn)證規(guī)則
rules: {
username: [
{ required: true, message: '請輸入用戶名', trigger: 'blur' },
{ min: 3, max: 20, message: '長度在 3 到 20 個(gè)字符', trigger: 'blur' }
],
password: [
{ required: true, message: '請輸入密碼', trigger: 'blur' },
{ min: 3, max: 20, message: '長度在 3 到 20 個(gè)字符', trigger: 'blur' }
]
}
}
},
methods: {
//查詢用戶方法
async getUsers() {
//get請求需要通過params屬性來傳對象
//用async/await 同步執(zhí)行異步代碼
let res = await this.$axios.get("users", {
params: this.pageData
});
//賦值
this.userList = res.data.data.users;
this.total = res.data.data.total;
},
//提交增加用戶方法
//這邊submitForm和validate都要加上async,內(nèi)部的await才能生效
async submitForm(formName) {
this.$refs[formName].validate(async valid => {
if (valid) {
//驗(yàn)證成功
//調(diào)用接口
let res = await this.$axios.post("users",this.form);
console.log(res);
if(res.data.meta.status===201){
//201表示成功請求并創(chuàng)建了新的資源恩脂,可以繼續(xù)執(zhí)行下一步
//關(guān)閉彈框
this.visible=false;
//重新獲取數(shù)據(jù)
this.getUsers();
}
} else {
//驗(yàn)證失敗
this.$message.error('請您輸入正確的信息')
return false;
}
});
},
},
//生命周期函數(shù)帽氓,回調(diào)函數(shù)
async created() {
//get請求需要通過params屬性來傳對象
// let res = await this.$axios.get("users", { params: this.pageData });
// this.userList = res.data.data.users;
// this.total = res.data.data.total;
//直接調(diào)用封裝后的代碼
this.getUsers();
}
};
</script>
Ⅲ.用戶狀態(tài)(啟用跟禁用該用戶)
餓了嗎組件 Switch 開關(guān)有change方法
//template中
<!-- slot-scope 廢棄,已經(jīng)被v-slot代替俩块,為插槽傳入table中的userList -->
<template slot-scope="scope">
<el-switch
v-model="scope.row.mg_state"
active-color="#13ce66"
inactive-color="#ff4949"
@change="statusChange(scope.row)">
</el-switch>
</template>
//js的methods中增加如下方法
<script>
async statusChange(data){
console.log(data);
let res = await this.$axios.put(`users/${data.id}/state/${data.mg.state}`);
}
</script>
Ⅳ.用戶刪除:傳入id即可
//在刪除按鈕增加delOne方法黎休,寫在methods內(nèi)
<script>
delOne(data){
console.log(data);
let id = data.id;
//提示用戶
this.$confirm('此操作將永久刪除用戶浓领,是否繼續(xù)?',"提示",{
confirmButtonText:"確定",
cancelButtonText:"取消",
type:"danger"
})
.then(async()=>{
//確定
let res = await this.$axios.delete(`users/${id}`);
//console.log(res);
//重新獲取用戶數(shù)據(jù)即可
this.getUsers();
})
.catch(()=>{
//取消
})
}
</script>
V.用戶編輯:
NO. | 用戶編輯 |
---|---|
1 | 進(jìn)入編輯狀態(tài) |
2 | 保存編輯結(jié)果 |
進(jìn)入編輯狀態(tài)
//template
<!-- 修改用戶的對話框 -->
<el-dialog title="修改用戶" :visible.sync="editVisible">
<!-- label-position控制label名的顯示位置势腮,注意要設(shè)置label-width才能生效 -->
<!-- 表單提交驗(yàn)證要加ref="userForm"屬性,并將userForm傳給提交按鈕 -->
<el-form :model="editForm" ref="editForm" label-position="left" label-width="70px">
<el-form-item label="用戶名" prop="username">
<!-- 用戶名不可改联贩,可以再input內(nèi)加disabled屬性,就能實(shí)現(xiàn)禁止修改 -->
<!-- 對于利用vue瀏覽器插件進(jìn)行修改的用戶捎拯,只能說牛逼泪幌,暫時(shí)沒有想到解決方法 -->
<el-input v-model="editForm.username" disabled autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="郵箱">
<el-input v-model="editForm.email" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="手機(jī)號">
<el-input v-model="editForm.mobile" autocomplete="off"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="editVisible = false">取 消</el-button>
<!-- 記住這邊的userForm要加單引號 -->
<el-button type="primary" @click="submitEdit('editForm')">確 定</el-button>
</div>
</el-dialog>
//js:
<script>
//1.data數(shù)據(jù)里增加
//編輯框是否可見
editVisible:false,
//編輯框的表單數(shù)據(jù)
editForm:{
username:'',
email:'',
mobile:''
//增加用戶的id,方便后續(xù)編輯使用
id:''
}
//2.methods里增加方法
//顯示編輯框
showEditDialog(data){
//打印data
console.log(data);
//顯示編輯框
this.editVisible = true;
//js的for in方法署照,遍歷editForm的key祸泪,將data對應(yīng)的key賦值給editForm的key
for (const key in this.editForm) {
this.editForm[key] = data[key];
}
//這種方法可能會在vue插件界面被篡改數(shù)據(jù),保險(xiǎn)點(diǎn)是用id再請求一個(gè)接口獲取數(shù)據(jù)
//如果id也被修改了呢建芙?一般不會這么無聊
}
</script>
保存編輯結(jié)果
//1.template:增加確定保存按鈕
<div slot="footer" class="dialog-footer">
<el-button @click="editVisible = false">取 消</el-button>
<!-- 記住這邊的userForm要加單引號 -->
<el-button type="primary" @click="submitEdit()">確 定</el-button>
</div>
//2.js:methods里增加方法
<script>
async submitEdit(){
let res = await this.$axios.put(
`users/${this.editForm.id}`,
this.editForm
);
console.log(res);
if(res.data.meta.status===200){
//關(guān)閉編輯框
this.editVisible = false;
//重新獲取數(shù)據(jù)即可
this.getUsers();
}
}
</script>
VI.分配角色
NO. | 分配角色 |
---|---|
1 | 彈出角色框没隘,分配角色 |
2 | 保存分配結(jié)果 |
餓了嗎組件 Select 選擇器
傳送門http://element-cn.eleme.io/#/zh-CN/component/select
//template
<!-- 分配角色的對話框 -->
<el-dialog title="分配角色" :visible.sync="roleVisible">
<!-- 就一個(gè)下拉框,不需要綁定表單數(shù)據(jù):model="editForm"禁荸,綁定角色數(shù)據(jù)就行 -->
<el-form label-position="left" label-width="100px">
<el-form-item label="當(dāng)前用戶">
{{selectUser.username}}
</el-form-item>
<el-form-item label="請選擇角色">
<el-select v-model="selectUser.role_name" placeholder="請選擇">
<el-option
v-for="item in roles"
:key="item.id"
:label="item.roleName"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="roleVisible = false">取 消</el-button>
<!-- 記住這邊的userForm要加單引號 -->
<el-button type="primary" @click="submitRole">確 定</el-button>
</div>
</el-dialog>
//js
<script>
// data里增加下面數(shù)據(jù)
//分配角色框是否顯示
roleVisible:false,
//當(dāng)前選中的用戶數(shù)據(jù)
selectUser:'',
//所有的角色數(shù)據(jù)
roles:''
//methods里增加下面的方法
//顯示角色對話框
async showRoleDialog(data){
this.roleVisible = true;
//通過data獲取用戶的名字右蒲,用戶的角色
//console.log(data);
//為了方便編碼,直接保存當(dāng)前選擇的用戶數(shù)據(jù)
this.selectUser = data;
//獲取所有的角色屡限,去數(shù)據(jù)庫獲绕废(角色列表接口)
let res = await this.$axios.get('roles');
console.log(res);
this.roles = res.data.data;
console.log(this.roles);
},
//保存分配結(jié)果
async submitRole(){
// 獲取用戶id,獲取角色id
// 調(diào)用接口
let res = this.$axios.put(`users/${this.selectUser.id}/role`,{
rid:this.selectUser.role_name
});
console.log(res);
//關(guān)閉對話框
this.roleVisible = false;
//提示用戶,之前已經(jīng)有axios攔截器了
}
</script>
V.分頁功能實(shí)現(xiàn)
餓了嗎組件 Pagination 分頁的一些屬性和方法
屬性/方法 | 作用 |
---|---|
1.@size-change="handleSizeChange" | pageSize (每頁條數(shù)) 改變時(shí)會觸發(fā)钧大,回調(diào)參數(shù)是新的pageSize |
2.@current-change="handleCurrentChange" | currentPage(當(dāng)前頁)改變時(shí)會觸發(fā)翰撑,回調(diào)參數(shù)是新的currentPage |
3.:page-sizes="[2, 4, 6, 8, 10]" | 這是下拉框可以選擇的,每選擇一行啊央,要展示多少內(nèi)容 |
4.:page-size="pageSize" | 顯示當(dāng)前行的條數(shù) |
5.:total="userList.length" | 總共有多少數(shù)據(jù) |
6.:data="userList.slice((currentPage-1)pagesize,currentPagepagesize) | userList取第幾頁的數(shù)據(jù)眶诈,最為重要的一句話 |
//html
<!-- 用戶數(shù)據(jù) -->
<el-row>
<el-col :sapn="24">
<!-- 如下對數(shù)據(jù)請求的處理,最為重要的一句話瓜饥,表示逝撬,userList取第幾頁的數(shù)據(jù) -->
<!-- :data="userList.slice((currentPage-1)*pagesize,currentPage*pagesize)" -->
<!-- arrayObject.slice(start,end)方法,參數(shù)是指數(shù)組對應(yīng)的下標(biāo)元素乓土,start參數(shù)必選束亏,end參數(shù)可選 -->
<el-table style="width: 100%" border
:data="userList.slice((pageData.pagenum-1)*pageData.pagesize,pageData.pagenum*pageData.pagesize)" >
<!-- 返回的數(shù)據(jù)沒有對應(yīng)的屬性名驹尼,把prop刪掉 -->
<!-- 增加type="index",會設(shè)置排序 -->
<el-table-column label="#" width="30" type="index"></el-table-column>
<el-table-column prop="username" label="姓名" width="180"></el-table-column>
<el-table-column prop="email" label="郵箱" width="300"></el-table-column>
<el-table-column prop="mobile" label="電話" width="300"></el-table-column>
<el-table-column prop="mg_state" label="用戶狀態(tài)" width="80">
<!-- slot-scope 廢棄,已經(jīng)被v-slot代替畸陡,為插槽傳入table中的userList -->
<template slot-scope="scope">
<el-switch
v-model="scope.row.mg_state"
active-color="#13ce66"
inactive-color="#ff4949"
@change="statusChange(scope.row)"
></el-switch>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="primary" plain size="mini" @click="showEditDialog(scope.row)" icon="el-icon-edit"></el-button>
<el-button type="danger" plain size="mini" @click="delOne(scope.row)" icon="el-icon-delete"></el-button>
<el-button type="warning" plain size="mini" @click="showRoleDialog(scope.row)" icon="el-icon-check"></el-button>
</template>
</el-table-column>
</el-table>
</el-col>
</el-row>
<!-- 底部的分頁 -->
<el-row>
<!-- size-change pageSize(每頁條數(shù))改變時(shí)會觸發(fā)的事件 -->
<!-- current-change currentPage(當(dāng)前頁)改變時(shí)會觸發(fā) -->
<!-- :page-sizes="[2, 4, 6, 8, 10]" 這是下拉框可以選擇的梯刚,每選擇一行输莺,要展示多少內(nèi)容 -->
<!-- :page-size="pageData.pagesize"顯示當(dāng)前行的條數(shù) -->
<!-- :total="userList.length" 這是總共有多少數(shù)據(jù) -->
<el-col :span="24">
<!-- 刪掉el-pagination如下的默認(rèn)事件 -->
<!-- @size-change="handleSizeChange"
@current-change="handleCurrentChange"-->
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageData.pagenum"
:page-sizes="[2, 4, 6, 8, 10]"
:page-size="pageData.pagesize"
layout="total, sizes, prev, pager, next, jumper"
:total="userList.length"
></el-pagination>
</el-col>
</el-row>
//js 在methods中加如下方法
<script>
handleSizeChange(size){
this.pageData.pagesize = size;//每頁下拉顯示數(shù)據(jù)
// console.log(this.pageData.pagesize);
},
handleCurrentChange(currentPage){
this.pageData.pagenum = currentPage;//點(diǎn)擊第幾頁
// console.log(this.pageData.pagenum);
}
</script>
本文同步發(fā)表在我的個(gè)人博客:https://www.lubaojun.com/