完成layout组件中嵌套的用户列表组件
(父)user文件夹下的index.vue:
<template>
<div class="user">
<!-- 搜索部分 -->
<el-card>
<el-form inline :model="searchForm" ref="searchRef" label-width="80px">
<el-form-item label="用户名称" prop="username">
<el-input style="width:240px" v-model="searchForm.username"></el-input>
</el-form-item>
<el-form-item label="用户邮箱" prop="email">
<el-input style="width:240px" v-model="searchForm.email"></el-input>
</el-form-item>
<el-form-item label="角色" prop="role_id">
<el-select style="width:240px" v-model="searchForm.role_id" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item style="margin-left:80px">
<el-button type="primary" @click="search">搜索</el-button>
<el-button @click="clear">清除</el-button>
<el-button type="primary" @click="add">+ 新增用户</el-button>
</el-form-item>
</el-form>
</el-card>
<!-- 内容部分 -->
<el-card style="margin-top:20px;">
<!-- 表格 -->
<el-table :data="userList" stripe style="width: 100%">
<el-table-column type="index" label="序号" width="80"></el-table-column>
<el-table-column prop="username" label="用户名"></el-table-column>
<el-table-column prop="phone" label="电话"></el-table-column>
<el-table-column prop="email" label="邮箱"></el-table-column>
<el-table-column prop="role" label="角色"></el-table-column>
<el-table-column prop="remark" label="备注"></el-table-column>
<el-table-column label="状态">
<template slot-scope="scope">
<span v-if="scope.row.status===0" style="color:red">禁用</span>
<span v-if="scope.row.status===1" style="color:#6ac144">启用</span>
</template>
</el-table-column>
<el-table-column label="操作" width="280">
<template slot-scope="scope">
<el-button type="primary" @click="editUser(scope.row)">编辑</el-button>
<el-button
:type="scope.row.status===0? 'success':'info'"
@click="changeStatus(scope.row.id)"
>{{scope.row.status===0?'启用':'禁用'}}</el-button>
<el-button @click="deleteUser(scope.row.username,scope.row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div style="margin-top:15px;text-align:center">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="page"
:page-sizes="[2, 4, 6, 8]"
:page-size="limit"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</div>
</el-card>
<!-- <UserEdit></UserEdit> -->
<!-- <user-edit ref="userEditRef"></user-edit> -->
<!-- 法2:传值给子组件 -->
<!-- 第二种:子组件传值父组件 监听传来的这个事件触发@editok="search-->
<user-edit ref="userEditRef" :modal="modal" @editok="search"></user-edit>
</div>
</template>
<script>
import UserEdit from "./user-add-or-update";
export default {
components: {
UserEdit
},
name: "UserList",
data() {
return {
// 模型
searchForm: {
username: "",
email: "",
role_id: "" //角色1、超级管理员 2管理员、3老师、 4学生
},
page: 1, // 查询时候的页码
limit: 2, // 查询时候的页容量(每页查询多少条)
userList: [], //存放发送请求得到的用户信息
total: 0,
modal: "add", ///法2:传值给子组件
options: [
{
value: "1",
label: "超级管理员"
},
{
value: "2",
label: "管理员"
},
{
value: "3",
label: "老师"
},
{
value: "4",
label: "学生"
}
]
};
},
methods: {
//先发送请求得到用户信息
async getUserData() {
const res = await this.$axios.get("/user/list", {
params: {
// 这个就相当于...this.searchForm
// username: this.searchForm.username,
// email: this.searchForm.email,
// role_id: this.searchForm.role_id
...this.searchForm,
page: this.page,
limit: this.limit
}
});
//console.log(res)
if (res.data.code == 200) {
this.userList = res.data.data.items;
this.total = res.data.data.pagination.total;
}
},
//搜索方法
search() {
//搜索要显示第一页的数据
this.page = 1;
this.getUserData();
},
// 清空方法
clear() {
// 法1:
// this.searchForm.username = ''
// this.searchForm.email = ''
// this.searchForm.role_id = ''
// 法2:调用form表单的重置方法要搭配form-item里面的prop使用
this.$refs.searchRef.resetFields();
// 显示第一页
this.search();
},
//每页的容量改变
handleSizeChange(val) {
this.limit = val; //页容量改变之后,是从第一页开始搜索
this.search();
},
// 当前页改变
handleCurrentChange(val) {
this.page = val; //当前页码改变之后,是从选中的那个页码开始发送请求
this.getUserData();
},
//改变当前行的用户状态
async changeStatus(id) {
const res = await this.$axios.post("/user/status", { id });
//console.log(res);
if (res.data.code == 200) {
this.$message({
message: "更改成功",
type: "success"
});
//刷新
this.getUserData();
}
},
// 删除该用户
deleteUser(username, id) {
this.$confirm(`确定删除${username}该用户吗?`, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(async () => {
const res = await this.$axios.post("/user/remove", { id });
console.log(res);
// 成功就弹出提示框
if (res.data.code == 200) {
this.$message({
type: "success",
message: "删除成功!"
});
// 并且要重新查询,展示第一页的数据内容
this.search();
}
})
.catch(() => {});
},
//新增用户
add() {
// 点击新增的时候子组件user-add-or-update.vue组件展示
this.$refs.userEditRef.dialogVisible = true;
// 并且修改他的子组件的modal值为add,表示是新增点的不是编辑点的
//法1.用refs方法传值子组件
// this.$refs.userEditRef.modal='add'
//法2:用props的方法传值子组件
this.modal = "add";
// 解决点击新增时在表单上输入一些内容按x或者取消后,再点击新增时,form表单内容还存在上一次输入的内容
//方法1:点击新增之前先把这个form内容全部清空
this.$refs.userEditRef.addForm = {
username: "", // 用户名
email: "", // 邮箱
phone: "", // 手机号
role_id: "", // 角色 1:超级管理员 2:管理员 3:老师 4:学生
status: "", // 状态 1:启用 0:禁用
remark: "" // 备注
};
// 方法1:再把校验清空
// this.$nextTick(()=>{
// this.$refs.userEditRef.$refs.addFormRef.clearValidate()
// })
//方法2:调用form表单的resetFields()方法不管内容还是校验全部清空
// 这个方法不是很好用还是有bug,当第一次点击编辑叉掉再点击新增时还是有内容,所以不用这个啦!
// this.$nextTick(() => {
// this.$refs.userEditRef.$refs.addFormRef.resetFields();
// });
// 方法3:
// 把这里的方法1中的this.$nextTick与修改用户的this.$nextTick里的这段代码写在user-add-or-update组件中去
// 写在watch里面,监听dialogVisible的变化
},
// 修改用户
editUser(row) {
this.modal = "edit";
//console.log(row);//这里的row就是点击编辑的那行的数据(是个对象)
this.$refs.userEditRef.dialogVisible = true;
//this.$refs.userEditRef.addForm = row 这种是浅拷贝,一改就把那行本来的数据也改了,所以不行
//this.$refs.userEditRef.addForm = {...row }//深拷贝第一种,但是这种只能拷贝一层
this.$refs.userEditRef.addForm = JSON.parse(JSON.stringify(row)); //深拷贝第二种,无论对象的层次有多深都能进行拷贝
// this.$nextTick(() => {
// this.$refs.userEditRef.$refs.addFormRef.clearValidate()
// });
}
},
created() {
// 获取用户列表数据,用户内容展示
this.getUserData();
}
};
</script>
<style>
</style>
项目说明:
01-左边菜单的选中状态
- 刚开始进来:
- 给模型中 defaultActive 赋值
- 刷新之后:
- 1、给 el-menu 绑定 :default-active=“defaultActive”
- 2、在 created 钩子中给 this.defaultActive = this.$route.fullPath 即可
- ps:下面这张图右边的三张图最后一张的也可以不用写那么麻烦,那个if(this.$route.fullpath==’/layout’){}这里面的可以不写,因为这个if里面主要想实现的功能是点击默认打开用户列表那栏的组件并且菜单高亮,其实直接在登录页面那里登录成功之后写跳转用户列表页面就行: this. $ router.push("/layout/user");
02-用户列表
-
搜索部分(el-card)
- el-form中加inline就是一行显示了
- 点击清除按钮时清空form表单中的内容有两种方式,以下:注意方式2是elementui中带的方法,一定要搭配prop用才有效
内容部分(el-card)
el-table、
el-pagination
更改状态
删除
(子)user文件夹下的user-add-or-update.vue:
<template>
<div class="userEdit">
<el-dialog center :visible.sync="dialogVisible" width="600px">
<!-- 标题 -->
<div class="title" slot="title">{{modal=='add'?'新增用户':'编辑用户'}}</div>
<!-- form表单 -->
<el-form label-width="80px" :model="addForm" :rules="rules" ref="addFormRef">
<el-form-item label="用户名" prop="username">
<el-input v-model="addForm.username"></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="phone">
<el-input v-model="addForm.phone"></el-input>
</el-form-item>
<el-form-item label="角色" prop="role_id">
<el-select v-model="addForm.role_id" placeholder="请选择">
<el-option label="超级管理员" :value="1"></el-option>
<el-option label="管理员" :value="2"></el-option>
<el-option label="老师" :value="3"></el-option>
<el-option label="学生" :value="4"></el-option>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="addForm.status" placeholder="请选择状态">
<el-option label="启用" :value="1"></el-option>
<el-option label="禁用" :value="0"></el-option>
</el-select>
</el-form-item>
<el-form-item label="用户备注" prop="remark">
<el-input v-model="addForm.remark"></el-input>
</el-form-item>
</el-form>
<!-- 两个按钮 -->
<span slot="footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="submit">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: "UserEdit",
//法2: 接受父组件传来的值用props方法
props: {
modal: {
type: String,
//没有传值的话就用这个default里面的
default: "add"
}
},
data() {
return {
dialogVisible: false, //控制Dialog的显示与否
//modal: "", //决定是新增还是编辑点的,add是新增,edit是编辑
addForm: {
username: "", // 用户名
email: "", // 邮箱
phone: "", // 手机号
role_id: "", // 角色 1:超级管理员 2:管理员 3:老师 4:学生
status: "", // 状态 1:启用 0:禁用
remark: "" // 备注
},
//校验规则
rules: {
username: [
{ required: true, message: "请输入用户名", trigger: "blur" }
],
email: [
{
required: true,
validator: (rule, value, callback) => {
if (!value) {
//函数就此打断
return callback(new Error("请输入邮箱号"));
}
//邮箱的正则表达式
const reg = /^[A-Za-z\d]+([-_.][A-Za-z\d]+)*@([A-Za-z\d]+[-.])+[A-Za-z\d]{2,4}$/; //邮箱正则
if (!reg.test(value)) {
return callback(new Error("邮箱不合法"));
}
callback();
},
trigger: "blur"
}
],
phone: [
{
required: true,
validator: (rule, value, callback) => {
if (!value) {
//,函数就此打断
return callback(new Error("请输入手机号"));
}
//手机号的正则表达式
const reg = /^1[3456789][0-9]{9}$/;
if (!reg.test(value)) {
return callback(new Error("手机号不合法"));
}
callback();
},
trigger: "blur"
}
],
role_id: [{ required: true, message: "请选择角色", trigger: "change" }],
status: [{ required: true, message: "请选择状态", trigger: "change" }],
remark: [{ required: true, message: "请输入备注", trigger: "blur" }]
}
};
},
methods: {
//点击确定按钮要做最后一次校验
submit() {
this.$refs.addFormRef.validate(async valid => {
if (!valid) return; //校验不成功就此打断
let res = "";
if (this.modal == "add") {
//成功就发送新增用户请求
res = await this.$axios.post("/user/add", this.addForm);
} else {
//成功就发送编辑用户请求
res = await this.$axios.post("/user/edit", this.addForm);
}
if (res.data.code == 200) {
this.$message({
message: this.modal == "add" ? "新增成功" : "编辑成功",
type: "success"
});
// 关闭当前对话框
this.dialogVisible = false;
// 刷新父组件的search方法,重新展示新增之后的数据
// 第一种 this.$parent.search()
// this.$parent.search();
// 第二种 this.$emit()
this.$emit('editok');
} else {
this.$message.error(res.data.message);
}
});
}
},
watch: {
dialogVisible(newValue){
if (newValue) {
this.$nextTick(()=>{
this.$refs.addFormRef.clearValidate(); //清空校验
})
}
}
// 用这种有一点点bug,当下拉框选择一个的时候再×掉再点开,校验就有了,因为值改变了
// dialogVisible(newValue){
// if (!newValue) {
// //当dialog对话框不可见的时候把校验都清空,此时dom都已经渲染过了不需要用$nextTick
// this.$refs.addFormRef.clearValidate()
// }
// }
},
};
</script>
项目说明:
03-用户新增&修改组件,就是这个弹出的对话框
- el-dialog弹出新增会话框
- 1、让列表组件与新增&修改组件形成父子关系
- 2、给子组件设置一个 ref,然后拿到子组件实例
- 3、拿到子组件实例之后,就可以更改子组件中的模型
- el-form:
- UI
- model & v-model 拿到值
- rules & prop
- 新增
- 1、对表单最后做一次校验
- 2、发送请求
- 3、请求成功之后的处理:弹出提示、关闭当前对话框、调用父组件的search方法