一、先把学员数据渲染到页面
1.新创建学生的一个数据库,在服务器创建一个student.js和数据库进行连接,创建一些规则:
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost/test') //和test数据库创建连接
module.exports = mongoose.model('Student', { //数据库的规则
stunum: { //学号
type: String,
required: true
},
name: { //姓名
type: String,
required: true
},
admissiondate: { //入学日期
type: String,
required: true
},
phone: { //电话号
type: String,
required: true
},
teacher: { //授课教师
type: String,
required: true
},
class: { //班级
type: String,
required: true
},
hobby: { //爱好
type: String,
},
commonSaying: { //口头禅
type: String,
}
})
2. 然后在数据库中添加数据:
mongo
use 数据库名称
db.createCollection("students")
db.students.insert([{'stunum':'001','name':'小新','admissiondate':'2015-11-11','phone':'12454686898','teacher':'吉永','class':'向日葵小班','hobby':'看动感超人','commonSaying':'嘿嘿 这没什么啦'},{'stunum':'002','name':'妮妮','admissiondate':'2015-11-11','phone':'12454686898','teacher':'吉永','class':'向日葵小班','hobby':'扮家家酒','commonSaying':'讨厌'},{'stunum':'003','name':'风间','admissiondate':'2015-11-11','phone':'12454686898','teacher':'吉永','class':'向日葵小班','hobby':'大概是读书吧','commonSaying':'小新!!'},{'stunum':'004','name':'阿呆','admissiondate':'2015-11-11','phone':'12454686898','teacher':'吉永','class':'向日葵小班','hobby':'收集石头','commonSaying':' '},{'stunum':'005','name':'正南','admissiondate':'2015-11-11','phone':'12454686898','teacher':'吉永','class':'向日葵小班','hobby':'小爱','commonSaying':'啊'}])
db.students.find()
3.然后把数据引入到router.js当中,让路由管理:
let Student = require('./student.js')
4.然后去学生组件把主体复制过去,并修改一下,作为学生组件的界面:
<template>
<div>
<h1>学生</h1>
<!-- 学生列表 -->
<el-table :data="studentTableData" height="400" border style="width: 100%">
<el-table-column type="index" label="序号"> </el-table-column>
<el-table-column prop="stunum" label="学号"> </el-table-column>
<el-table-column prop="name" label="姓名"> </el-table-column>
<el-table-column prop="admissiondate" label="入学时间"> </el-table-column>
<el-table-column prop="phone" label="电话"> </el-table-column>
<el-table-column prop="teacher" label="授课教师"> </el-table-column>
<el-table-column prop="class" label="班级"> </el-table-column>
<el-table-column prop="hobby" label="爱好"> </el-table-column>
<el-table-column prop="commonSaying" label="口头禅"> </el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button size="mini" @click="handleEdit(scope.row._id)">编辑</el-button>
<el-button size="mini" type="danger" @click="handleDelete(scope.row._id)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
5.并把相应方法在下面创建出来:
<script>
export default {
name: "Student",
data() {
return {
studentTableData: [],
};
},
methods: {
handleEdit() { },
handleDelete() { },
}
}
</script>
6.然后回后台服务器把接口写出来,这个和教师接口一样啦,这里是一个接口多用,既能拿到学生列表,又可以分页,还能按条件查询,由于这里不传参时,直接能拿到学生列表,我们先把学生的数据展示出来:
// 学生列表
router.post("/student/list", (req, res) => {
let page = req.body.page || 1; //页数
let size = req.body.size || 10; //一页显示多少条
let searchMap = req.body.searchMap || {}
// console.log(page, size, searchMap);
let obj = {}
searchMap.jobnumber ? obj["jobnumber"] = searchMap.jobnumber : obj
searchMap.name ? obj["name"] = searchMap.name : obj
searchMap.role ? obj["role"] = searchMap.role : obj
searchMap.entrydate ? obj["entrydate"] = searchMap.entrydate : obj
Student.find(obj, (err, data) => {
if (err) {
return res.status(500).json({
code: 3000,
flag: false,
message: "服务器后台错误"
})
}
let content = data.length
//skip跳过多少条,limit查询多少个,exec当前面的代码,执行完毕后,产生的回调
Student.find(obj).skip((page - 1) * parseInt(size)).limit(parseInt(size)).exec((err, data) => {
if (err) {
return res.status(500).json({
code: 3000,
flag: false,
message: "服务器后台错误"
})
}
return res.status(200).json({
"code": 2000,
"flag": true,
"message": "查询成功",
"data": {
content,
"rows": data
}
})
})
})
})
7.然后再前台的api中创建一个student.js,这次我们用默认导出的方式:
import request from "@/utils/request";
// 这里采用默认导出的方式:
export default {
getStuList() {//获得学生列表
return request({
url: "/student/listPage",
method: "post",
})
}
}
8.然后要在学生组件中,把student.js引入进来:
import studentApi from "@/api/student.js";
9.创建stuList()方法,渲染数据:
<script>
import studentApi from '@/api/student';
export default {
name: "Student",
data() {
return {
studentTableData: [],
};
},
created() {
this.stuList()
},
methods: {
// 获得学生列表
stuList() {
studentApi.getStuList().then(res => {
console.log(res);
this.studentTableData = res.data.data.rows
}).catch()
},
handleEdit() { },
handleDelete() { },
}
}
</script>
10.在created中使用一下:
created () {
this.getList()
}
11.此时,页面信息被渲染到页面了。
二、分页
1.先把分页模板在学生组件中写出来:
<!-- 分页区 -->
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage"
:page-sizes="pageSizes" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="total">
</el-pagination>
2.在data中,把数据添加上去:
data() {
return {
// 学生列表
studentTableData: [],
// 分页
currentPage: 1,//当前页数
pageSize: 5,//每页显示多少条数据
pageSizes: [5, 10, 15, 20],// 每页显示个数选择器的选项设置
total: 0,
};
},
3.并把相应方法在下面创建出来:
//element-ui 的控制表格方法
handleSizeChange(val) {
this.pageSize = val;
this.stuList()
},
//element-ui 的控制表格方法
handleCurrentChange(val) {
this.currentPage = val;
this.stuList()
},
4.现在分页模板能渲染到页面中了,接下来,我们把数据给分页传过去,在api/student.js中,添加:
import request from "@/utils/request";
// 这里采用默认导出的方式:
export default {
getStuList(page, size) { //获得学生列表
return request({
url: "/student/listPage",
method: "post",
data: {
page,
size
}
})
}
}
5.再回到学生组件,把数据渲染到页面:
// 获得学生列表
stuList() {
studentApi.getStuList(this.currentPage, this.pageSize).then(res => {
console.log(res);
let resArr = res.data
this.total = resArr.data.content
this.studentTableData = resArr.data.rows
}).catch(err => {
console.log(err);
})
},
6.现在分页的所有功能就实现了。
三、条件查询实现
在列表上方添加查询功能,通过 学号 、学员姓名、授课教师等条件查询
1. 修改 src\views\student\index.vue ,增加条件查询模板代码:
<!-- 搜索区 -->
<el-form :inline="true" :model="searchMap" ref="searchForm" class="demo-form-inline">
<!-- prop 表单域 model 字段,在使用 validate、resetFields 方法的情况下,该属性是必填的 -->
<el-form-item label="学号" prop="stunum">
<el-input v-model="searchMap.stunum" placeholder="学号"></el-input>
</el-form-item>
<el-form-item label="姓名" prop="name">
<el-input v-model="searchMap.name" placeholder="姓名"></el-input>
</el-form-item>
<el-form-item label="授课教师" prop="teacher">
<el-input v-model="searchMap.teacher" placeholder="授课教师"></el-input>
</el-form-item>
<el-form-item label="入学时间" prop="admissiondate">
<el-date-picker type="date" placeholder="选择日期" value-format="yyyy-MM-dd"
v-model="searchMap.admissiondate"></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button>
<el-button @click="resetForm('searchForm')">重置</el-button>
<el-button type="text" @click="addMember">新增</el-button>
</el-form-item>
</el-form>
data 选项中的searchMap对象中指定条件字段:
data() {
return {
// 学生列表
studentTableData: [],
// 分页
currentPage: 1,//当前页数
pageSize: 5,//每页显示多少条数据
pageSizes: [5, 10, 15, 20],// 每页显示个数选择器的选项设置
total: 0,
// 搜索栏
searchMap: {
stunum: '',
name: '',
teacher: '',
admissiondate: ''
}
};
},
为了页面不报错,也先把相应方法在methods里创建出来:
// 查询
onSubmit() {
// 点击查询,重新分页并获取学生列表
this.currentPage = 1;
this.stuList()
},
//element-ui 的重置方法
resetForm(formName) {
this.$refs[formName].resetFields();
// 点击查询,重新分页并获取学生列表
this.currentPage = 1;
this.stuList()
},
// 新增
addMember() { },
为了点击查询时,把要查询的数据发送到后台当中,所以回到api下的students.js里和学生组件的stuList()里把searchMap传过去:
import request from "@/utils/request";
// 这里采用默认导出的方式:
export default {
getStuList(page, size,searchMap) { //获得学生列表
return request({
url: "/student/listPage",
method: "post",
data: {
page,
size,
searchMap
}
})
}
}
// 获得学生列表
stuList() {
studentApi.getStuList(this.currentPage, this.pageSize,this.searchMap).then(res => {
console.log(res);
let resArr = res.data
this.total = resArr.data.content
this.studentTableData = resArr.data.rows
}).catch(err => {
console.log(err);
})
},
再回到服务器后台里,改掉数据:
searchMap.stunum ? obj["stunum"] = searchMap.stunum : obj
searchMap.name ? obj["name"] = searchMap.name : obj
searchMap.teacher ? obj["teacher"] = searchMap.teacher : obj
searchMap.admissiondate ? obj["admissiondate"] = searchMap.admissiondate : obj
// 分页// 学生列表
router.post("/student/listPage", (req, res) => {
let page = req.body.page || 1; //页数
let size = req.body.size || 10; //一页显示多少条
let searchMap = req.body.searchMap || {} //用来做条件查询的
// console.log(page, size, searchMap);
let obj = {} //用来接收搜索栏数据,实现按条件查询
// searchMap中是否包含jobnumber、name、role、entrydate,如果有,把他们存到obj里
searchMap.stunum ? obj["stunum"] = searchMap.stunum : obj
searchMap.name ? obj["name"] = searchMap.name : obj
searchMap.teacher ? obj["teacher"] = searchMap.teacher : obj
searchMap.admissiondate ? obj["admissiondate"] = searchMap.admissiondate : obj
// console.log(searchMap, obj);
Student.find(obj).then((data, err) => { //去数据库中查找
if (err) {
return res.status(500).json({
code: 3000,
flag: false,
message: "服务器后台错误"
})
}
let content = data.length
//skip跳过多少条,limit查询多少个,exec当前面的代码,执行完毕后,产生的回调
Student.find(obj).skip((page - 1) * parseInt(size)).limit(parseInt(size)).exec().then((data, err) => {
console.log(obj, page, size, data);
if (err) {
return res.status(500).json({
code: 3000,
flag: false,
message: "服务器后台错误"
})
}
return res.status(200).json({
"code": 2000,
"flag": true,
"message": "查询成功",
"data": {
content,
"rows": data
}
})
})
})
})
测试:查询成功!重置成功!
2. 授课教师选择
效果是:点击输入框,弹出一个对话框,对话框里直接复用教师管理组件,
2.1. 将 teacher\index.vue 导入 student\index.vue 作为子组件使用。注意: components 记得注册 Teacher作为子组件
import Teacher from "../teacher/index.vue";//1.先引入
export default {
components: {//2.在这里注册
Teacher//作为子组件传过来
},}
2.2使用 dialog 对话框组件,包裹 Teacher 组件:
<!-- 弹出教师组件 -->
<el-dialog title="请选择教师" :visible.sync="dialogFormVisible">
<Teacher :isDialog="isDialog" />
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogFormVisible = false">确 定</el-button>
</div>
</el-dialog>
2.3在 student\index.vue 组件的 data 选项中定义 dialogFormVisible控制对话框
// 控制教师组件弹出的
dialogFormVisible: false,
2.4. 设置当点击输入框时,弹出框才弹出,@click.native 点击事件。注意: el-input 是组件,要在组件元素监听原生事件,需要使用 v-on:原生事件名.native="处理函数",readonly 只读框 :
<el-form-item label="授课教师" prop="teacher">
<el-input v-model="searchMap.teacher" placeholder="授课教师" @click.native="dialogFormVisible = true" readonly></el-input>
</el-form-item>
2.5教师页面在弹出时候很多是我们不需要的, 进行优化,父组件student向子组件teacher传递数据: 子组件通过 props 声明接收,向教师 Teacher 子组件传入一个参数 isDialog , 如果是弹出窗口, 则弹出页面隐藏一些功能. (我们自定义一个属性,isDialog,让它的布尔值来决定他是否隐藏)在 student\index.vue 上的 组件data标签上绑定属性 :isDialog="true":
data() {
return {
// 学生列表
studentTableData: [],
// 分页
currentPage: 1,//当前页数
pageSize: 5,//每页显示多少条数据
pageSizes: [5, 10, 15, 20],// 每页显示个数选择器的选项设置
total: 0,
// 搜索栏
searchMap: {
stunum: '',
name: '',
teacher: '',
admissiondate: ''
},
// 控制教师组件弹出的
dialogFormVisible: false,
// 控制教师组件有些内容是否显示的
isDialog: true,
};
},
<!-- 弹出教师组件 -->
<el-dialog title="请选择教师" :visible.sync="dialogFormVisible">
<Teacher :isDialog="isDialog" />
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogFormVisible = false">确 定</el-button>
</div>
</el-dialog>
子组件接收:
export default {
name: "Teacher",
props: {
isDialog: Boolean
},
....
}
采用 v-if=“!isDialog” 来隐藏,在子组件中:
搜索区添加v-if=“!isDialog”:
<!-- 搜索区 -->
<el-form :inline="true" :model="searchMap" ref="searchForm" class="demo-form-inline" v-if="!isDialog">
<!-- prop 表单域 model 字段,在使用 validate、resetFields 方法的情况下,该属性是必填的 -->
<el-form-item label="工号" prop="jobnumber">
<el-input v-model="searchMap.jobnumber" placeholder="工号"></el-input>
</el-form-item>
<el-form-item label="姓名" prop="name">
<el-input v-model="searchMap.name" placeholder="姓名"></el-input>
</el-form-item>
<el-form-item label="职务" prop="role">
<el-select v-model="searchMap.role" placeholder="职务">
<el-option :key="index" v-for="(item, index) in roleOptions" :label="item.name"
:value="item.type"></el-option>
</el-select>
</el-form-item>
<el-form-item label="入职时间" prop="entrydate">
<el-date-picker type="date" placeholder="选择日期" value-format="yyyy-MM-dd"
v-model="searchMap.entrydate"></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button>
<el-button @click="resetForm('searchForm')">重置</el-button>
<el-button type="text" @click="addMember">新增</el-button>
</el-form-item>
</el-form>
教师列表添加v-if=“!isDialog”:
<!-- 教师列表 -->
<el-table :data="teacherTableData" height="400" border style="width: 100%">
<el-table-column type="index" label="序号" v-if="!isDialog"> </el-table-column>
<el-table-column prop="jobnumber" label="工号" v-if="!isDialog"> </el-table-column>
<el-table-column prop="name" label="姓名"> </el-table-column>
<el-table-column prop="role" label="职务">
<template slot-scope="scope">
<span style="margin-left: 10px">{{ scope.row.role | roleFilter }}</span>
</template>
</el-table-column>
<el-table-column prop="entrydate" label="入职时间" v-if="!isDialog"> </el-table-column>
<el-table-column prop="phone" label="电话"> </el-table-column>
<el-table-column label="操作" v-if="!isDialog">
<template slot-scope="scope">
<el-button size="mini" @click="handleEdit(scope.row._id)">编辑</el-button>
<el-button size="mini" type="danger" @click="handleDelete(scope.row._id)">删除</el-button>
</template>
</el-table-column>
</el-table>
分页区:
<!-- 分页区 -->
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage"
:page-sizes="pageSizes" :page-size="pageSize"
:layout="!isDialog ? 'total, sizes, prev, pager, next, jumper' : ' prev, pager, next'" :total="total">
</el-pagination>
最终效果:
2.6. 现在要实现:当点击子组件列表中某一行教师,即选中;选中的那个教师名字出现在父组件学员管理 的授课教师输入框中
在 teacher\index.vue 组件的 el-table 表格组件上配置 @current-change="getTeacherName":
<!-- 教师列表 -->
<!-- @current-change 点击某一行,拿到这一行的数据 -->
<el-table :data="teacherTableData" height="400" border style="width: 100%" @current-change="getTeacherName">
<el-table-column type="index" label="序号" v-if="!isDialog"> </el-table-column>
<el-table-column prop="jobnumber" label="工号" v-if="!isDialog"> </el-table-column>
<el-table-column prop="name" label="姓名"> </el-table-column>
<el-table-column prop="role" label="职务">
<template slot-scope="scope">
<span style="margin-left: 10px">{{ scope.row.role | roleFilter }}</span>
</template>
</el-table-column>
<el-table-column prop="entrydate" label="入职时间" v-if="!isDialog"> </el-table-column>
<el-table-column prop="phone" label="电话"> </el-table-column>
<el-table-column label="操作" v-if="!isDialog">
<template slot-scope="scope">
<el-button size="mini" @click="handleEdit(scope.row._id)">编辑</el-button>
<el-button size="mini" type="danger" @click="handleDelete(scope.row._id)">删除</el-button>
</template>
</el-table-column>
</el-table>
在 teacher\index.vue 组件定义 getTeacherName函数,向父组件传递点击数据。(子组件向父组件传递数据:通过 $emit 触发事件的方式 ):
// 向父组件传name
getTeacherName(val) {
this.$emit("get-teacher-name",val)
},
在父组件 student\index.vue中监听自定义事件 get-teacher-name:
<Teacher :isDialog="isDialog" @get-teacher-name="handleTName"/>
在父组件student\index.vue中添加 事件触发的函数handleTName进行回显数据:
// 得到子组件数据:教师名字
handleTName(val) {
this.searchMap.teacher = val.name;//数据回显到授课教师输入框内
this.dialogFormVisible = false//关闭窗口
},