目录
1.2.1在 src/api 下创建 teacher.js , 调用接口代码如下:
1.2.3在 src\views\teacher\index.vue 中, 添加 js 代码如下:
1.3.1修改 src\views\teacher\index.vue
1.6.1 修改 src\views\teacher\index.vue ,增加条件查询模板代码
1.6.2 在 data 选项声明 roleOptions属性用于下拉框 ,并将全局的赋值给它
2.1.1 在 src\views\teacher\index.vue 中分页区域的下方,新增对话框形式表单数据模板
2.1.2 在 methods 中添加 handleAdd() 函数
2.2.1 在新增窗口的 el-form 上绑定属性 :rules="rules"
3.2.1 src\api\teacher.js 导出的默认对象中,添加ID查询方法 getById和更新方法 update
3.2.2 在 src\views\teacher\index.vue 中的 handleEdit 方法做如下修改:
4.2.1 src\api\teacher.js 导出的默认对象中,添加 deleteById 方法
4.2.2 在 src\views\teacher\index.vue 中的 handleDele 方法做如下修改:
一、教师管理-列表查询
1.1 nodejs 添加数据列表接口
1.1.1 创建teacher.js
node.js配置
//!读写数据库
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/stu');
//?定义规则对象
var Schema = mongoose.Schema;//声明mongoose下的一个规则
var userSchema = new Schema({//创建一个规则的对象,生成一个这样规则的实例
jobnumber: {//工号
type: String,
require: true
},
name: {
type: String,
require: true
},
role: {//职位
type: String,
require: true
},
entrydate: {//入职时间
type: String,
require: true
},
phone: {
type: String,
require: true
}
})
module.exports = mongoose.model('Teacher', userSchema);//默认去找表名为teachers
1.1.2 router.js中添加获取教师列表方法
在router.js中导入teacher.js
var Teacher = require('./teacher.js')
添加获取教师列表方法
router.get('/teacher/list', function (req, res) {
Teacher.find({}, function (err, data) {//因为要查询所有,所以条件可以不用写
if (err) {
res.status(500).json({
code: 4000,
flag: false,
message: 'server error'
})
}
return res.status(200).json({
code: 2000,
flag: true,
message: '查找教师信息成功',
data: {
total: data.length,//后面涉及到分页问题,需要获取数组长度
rows: data,
}
})
})
})
1.2 Api调用接口
1.2.1在 src/api 下创建 teacher.js , 调用接口代码如下:
import request from '@/utils/request.js'
export default {
getList() {
return request({
url: '/teacher/list',
method: 'get',
})
}
}
1.2.2在数据库中手动添加数据,以供测试:
成功查询:
1.2.3在 src\views\teacher\index.vue 中, 添加 js 代码如下:
<script>
import teacherApi from '@/api/teacher.js'
//因为在teacher.js中默认导出对象,所以接受的时候就不能用大括号的形式去接收
export default {
data() {
return {
tableData: [],//调用的element-ui中的table的data为tableData
total: 0
}
},
components: {},
created() {
this.fetchData();//在钩子函数中调用下面写的方法
},
methods: {
fetchData() {
teacherApi.getList().then(response => {
const resp = response.data;
// console.log(resp);
this.tableData = resp.data.rows;
this.total = resp.data.total;
})
}
},
}
</script>
1.3 列表模板
1.3.1修改 src\views\teacher\index.vue
编写模板代码:表格采用的是固定表头
参考: Element - The world's most popular Vue UI framework
<template>
<div class="table">
<el-table
:data="tableData"
height="250"
border
style="width: 100%"
>
<el-table-column
type="index"
label="序号"
width="80"
>
<!-- 用index绑定序号的时候,前边不能用prop,而需要用type -->
</el-table-column>
<el-table-column
prop="jobnumber"
label="工号"
width="180"
>
</el-table-column>
<el-table-column
prop="name"
label="姓名"
width="180"
>
</el-table-column>
</el-table-column>
<el-table-column
prop="role"
label="职位"
width="180"
>
</el-table-column>
</el-table-column>
<el-table-column
prop="entrydate"
label="入职时间"
width="180"
>
</el-table-column>
<el-table-column
prop="phone"
label="联系方式"
>
</el-table-column>
<el-table-column label="操作">
<!--
在Element-ui中,要在某一个元素中放一个按钮的话,
需要在按钮外面套一层template标签,因为element框架封装时的要求.
-->
<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>
1.4 过滤器实现数据转换
1.4.1通过 filters 选项来定义过滤器来实现转换
渲染后发现职务类型是编号,应该将类型编号 转为名称.
JS 脚本处声明一个全局职务类型数组, 组件对象的 filters 选项指定转换规则.
const roleOptions = [//全局定义职位类型的数组
{
type: '1', name: '班主任'
},
{
type: '2', name: '数学老师'
},
{
type: '3', name: '语文老师'
},
{
type: '4', name: '英语老师'
}
];
filters: {//过滤器
roleFilter(type) {
const obj = roleOptions.find(item => item.type === type)
//箭头函数后边是查询条件 find方法中是function
/* 表示数组中某一项的type如果与传进来的type一致,就把这项返回 */
return obj ? obj.name : null;//三元表达式,如果没有obj就返回空值
}
},
1.4.2 修改 模板代码
<el-table-column
prop="role"
label="职位"
width="180"
>
<template slot-scope="scope">
<span>{{scope.row.role | roleFilter}}</span>
</template>
</el-table-column>
1.5 分页功能实现
为列表数据添加分页功能,使用分页组件完成分页功能。
参考:Element - The world's most popular Vue UI framework
添加数据,以达到分页显示的目的:
1.5.1 分页模板
修改 src\views\teacher\index.vue , template 标签中添加页面模板代码:
<!-- 分页功能 -->
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="this.currentPage"
:page-sizes="[5, 10, 20]"
:page-size="this.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="this.total"
>
</el-pagination>
注意:添加在 div 里面,因为 template 里面只能有唯一根节点.
返回数据以及方法:
data() {
return {
tableData: [],
total: 0,
currentPage: 1,
pageSize: 10,
seachMap: {//所有教师的所有项
jobnumber: '',
name: '',
role: '',
entrydate: ''
}
}
},
filters: {//过滤器
roleFilter(type) {
const obj = roleOptions.find(item => item.type === type)//箭头函数后边是查询条件 find方法中是function
/* 表示数组中某一项的type如果与传进来的type一致,就把这项返回 */
return obj ? obj.name : null;//三元表达式,如果没有obj就返回空值
}
},
components: {},
created() {
this.fetchData();//在钩子函数中调用下面写的方法
},
methods: {
fetchData() {
teacherApi.search(this.currentPage, this.pageSize, this.seachMap).then(response => {
const resp = response.data;
// console.log(resp);
this.tableData = resp.data.rows;
this.total = resp.data.total;//记录读取多少条
})
},
handleSizeChange(val) {
console.log(`每页 ${val} 条`);
this.pageSize = val;
this.fetchData();
},
handleCurrentChange(val) {
console.log(`当前页: ${val}`);
this.currentPage = val;
this.fetchData();
}
}
1.5.2 Api 调用接口
修改 src\api 下的 teacher.js , 在导出的默认对象中,增加分页查询方法
search(page, size, searchMap) {//通过axios请求将这三个参数传到服务端
return request({
url: '/teacher/search',
method: 'post',
data: {
page,//page 当前要查询的页码
size,//size 每页显示条数
searchMap//所有教师的所有项
}
})
}
修改fetchData方法:
fetchData() {
teacherApi.search(this.currentPage, this.pageSize, this.seachMap)
.then(response => {
const resp = response.data;
// console.log(resp);
this.tableData = resp.data.rows;
this.total = resp.data.total;//记录读取多少条
})
},
1.5.3 nodejs添加会员分页模拟接口
router.js中添加方法:
//?修改教师信息(分页)
router.post('/teacher/list', function (req, res) {
const body = req.body;
//* 前端传入
let page = body.page || 1;//如果传的时候没有值,默认值就为1.
let size = body.size || 10;
let searchMap = body.searchMap || {};
//* 后端真正查询条件
const obj = {};
searchMap.jobnumber ? obj["jobnumber"] = searchMap.jobnumber : obj;
//判断searchMap中是否有jobnumber这一项,如果存在就在obj中添加一项jobnumber等于searchMap.jobnumber,没有就为空.
searchMap.name ? obj["name"] = searchMap.name : obj;
searchMap.role ? obj["role"] = searchMap.role : obj;
searchMap.entrydate ? obj["entrydate"] = searchMap.entrydate : obj;
Teacher.find(obj, function (err, data) {//obj有内容就按照obj的内容去查询,没有内容就相当于空对象
//todo find方法无论有没有条件,返回的都是数组.
if (err) {
return res.status(500).json({
code: 3000,
flag: false,
message: 'server error'
})
}
let count = data.length;//查询到数据后,记录data中有多少数据.
//*进行分页查询
Teacher.find(obj).skip((page - 1) * parseInt(size)).limit(parseInt(size)).exec(function (err, data) {
//skip 跳过 limit 截取.
//通过find查找, 拿到数据后进行skip,limit.这种写法无法写回调函数,通过exec方法来拿到返回值
if (err) {
res.status(500).json({
code: 3000,
flag: false,
message: 'server error'
})
}
return res.status(200).json({
code: 2000,
flag: true,
message: '成功查询! 查询信息如下',
data: {
total: count,
rows: data
}
})
})
})
})
成功分页查询:
1.6 条件查询实现
在列表上方添加查询条件
1.6.1 修改 src\views\teacher\index.vue ,增加条件查询模板代码
<!-- 条件查询 -->
<el-form
:inline="true"
:model="searchMap"
ref="searchForm"
class="demo-form-inline"
>
<el-form-item prop="jobnumber">
<el-input
v-model="searchMap.jobnumber"
placeholder="工号"
></el-input>
</el-form-item>
<el-form-item prop="name">
<el-input
v-model="searchMap.name"
placeholder="姓名"
></el-input>
</el-form-item>
<el-form-item prop="role">
<el-select
v-model="searchMap.role"
placeholder="教师职务"
>
<!-- 循环 绑定相应数据 -->
<el-option
v-for="option in roleOptions"
:key="option.type"
:label="option.name"
:value="option.type"
></el-option>
</el-select>
</el-form-item>
<el-form-item prop="entrydate">
<span class="demonstration"></span>
<!-- 使用 value-format 保证格式与数据库中一致 -->
<el-date-picker
value-format="yyyy-MM-dd"
v-model="searchMap.entrydate"
type="date"
placeholder="入职时间"
>
</el-date-picker>
</el-form-item>
<el-form-item>
<el-button
type="primary"
@click="searchData"
>查询</el-button>
<el-button type="primary">新增</el-button>
<el-button
type="primary"
@click="resetForm"
>重置</el-button>
</el-form-item>
</el-form>
条件查询表单中需要在每一个el-form-item标签中添加prop属性,绑定相应的key值,不然获取不到数据.
1.6.2 在 data 选项声明 roleOptions属性用于下拉框 ,并将全局的赋值给它
v-model绑定必须是相应实例里的数据.
data() {
return {
tableData: [],
total: 0,
currentPage: 1,
pageSize: 10,
searchMap: {//所有教师的所有项
jobnumber: '',
name: '',
role: '',
entrydate: ''
},
roleOptions//ES6
}
},
1.6.3 methods中添加searchData方法
searchData() {
this.currentPage = 1;//将页码设置回1,防止后台只查询到1条数据,但是却返回其他页码,从而数据返回空
this.fetchData();
},
resetForm(formName) {
this.$refs[formName].resetFields();
},
测试,成功查询:
二、教师管理-新增
2.1 新增窗口实现
2.1.1 在 src\views\teacher\index.vue 中分页区域的下方,新增对话框形式表单数据模板
el-dialog 标答属性 title 窗口标题,visible.sync 是否弹出窗口
<!-- 新增教师弹窗 -->
<el-dialog
title="教师信息编辑"
:visible.sync="dialogFormVisible"
width='500px'
><!-- :visible.sync 控制弹窗 -->
<el-form
:model="teacher"
ref="teacherForm"
label-width='100px'
label-position='right'
style="width:400px"
>
<el-form-item
label="工号"
prop='jobnumber'
>
<el-input
v-model="teacher.jobnumber"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item
label="姓名"
prop='name'
>
<el-input
v-model="teacher.name"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item
label="职务"
prop='role'
>
<el-select
v-model="teacher.role"
placeholder="请选择..."
>
<el-option
v-for="option in roleOptions"
:key="option.type"
:label="option.name"
:value="option.type"
></el-option>
</el-select>
</el-form-item>
<el-form-item
prop="entrydate"
label='入职时间'
>
<span class="demonstration"></span>
<!-- 使用 value-format 保证格式与数据库中一致 -->
<el-date-picker
value-format="yyyy-MM-dd"
v-model="teacher.entrydate"
type="date"
placeholder="入职时间"
>
</el-date-picker>
</el-form-item>
<el-form-item
label="电话"
prop='phone'
>
<el-input
v-model="teacher.phone"
autocomplete="off"
></el-input>
</el-form-item>
</el-form>
<div
slot="footer"
class="dialog-footer"
>
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary">确 定</el-button>
</div>
</el-dialog>
</div>
弹窗实现:
2.1.2 在 methods 中添加 handleAdd() 函数
打开新增对话框关闭窗口后,再次打开窗口,会发现表单里依然有数据,应当清除数据。
handleAdd() {
this.dialogFormVisible = true;
// this.$refs['teacherForm'].resetFields();
/* 直接调用方法的时候,DOM层渲染的窗口没加载出来,表单也就没有生成,
但是this.$的方法是异步加载的,表单未加载出来的时候重置功能就开始执行,找不到表单实例,所以控制台会报错 */
this.$nextTick(() => {
this.$refs['teacherForm'].resetFields();
})
/* this.$nextTick()它是一个异步事件,当渲染结束之后 ,它的回调函数才会被执行
弹出窗口打开之后 ,需要加载Dom, 就需要花费一点时间,等待它加载完dom之后,再进行调用resetFields方法,重置表单和清除样式*/
},
2.2 表单数据校验
2.2.1 在新增窗口的 el-form 上绑定属性 :rules="rules"
<el-form
:model="teacher"
ref="teacherForm"
label-width='100px'
label-position='right'
style="width:400px"
:rules='rules'
>
2.2.2 在 data 选项中添加 rules 属性进行校验,对工号,姓名 校验
rules:{
jobnumber: [{ required: true, message: '请输入工号', trigger: 'blur' }],
name: [{ required: true, message: '请输入姓名', trigger: 'blur' }]
},
2.3 表单数据提交
2.3.1 nodejs 添加新增教师接口
router.js中新增方法
//?新增教师
router.post('/teacher/add', function (req, res) {
var body = req.body;
new Teacher(body).save(function (err) {//往mongo中添加数据 使用 new Teacher().save
if (err) {//只需要判断是否存在,不需要将存的数据再返回来一遍
return res.status(500).json({
code: 3000,
flag: false,
message: 'server error'
})
}
return res.status(200).json({
code: 2000,
flag: true,
message: '成功添加'
})
})
})
2.3.2 Api调用接口
src\api\teacher.js 导出的默认对象中,添加调用新增接口的方法
add(teacher) {
return request({
url: '/teacher/add',
method: 'post',
data: teacher
})
}
在 src\views\teacher\index.vue 中的 addData 方法中提交数据,代码如下:
addData(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
//向数据库中添加数据,成功后重新查询刷新列表
// alert('submit!');
teacherApi.add(this.teacher).then(response => {
const resp = response.data;
if (resp.flag) {
this.fetchData();//新增成功,刷新列表数据
this.dialogFormVisible = false;//添加完成后,自动关闭弹窗
this.$message({
message: '添加教师信息成功',
type: 'success'
})
} else {
this.$message({
message: resp.message,
type: 'warning'
})
}
})
} else {
//返回添加失败提示
console.log('error submit!!');
return false;
}
});
},
添加教师信息成功:
三、 教师管理-修改
3.1 nodejs添加接口
3.1.1 ID 查询数据接口
//?根据id查找一条教师信息
router.get('/teacher', function (req, res) {
Teacher.findById(req.query.id, function (err, data) {
if (err) {
return res.status(500).json({
code: 3000,
flag: false,
message: 'server error'
})
}
return res.status(200).json({
code: 2000,
flag: true,
message: '根据id查找教师信息成功',
data: data
})
})
})
3.1.2 提交修改数据接口
//?根据id修改一条教师信息(put方法,在使用上与post方法一样)
router.put('/teacher', function (req, res) {
var id = req.body._id;//与前端传过来的key值要对应
Teacher.findByIdAndUpdate(id, req.body, function (err) {//findByIdAndUpdate方法参数分别为,id,整个对象,方法
if (err) {
return res.status(500).json({
code: 3000,
flag: false,
message: 'server error'
})
}
return res.status(200).json({
code: 2000,
flag: true,
message: '修改教师信息成功'
})
})
})
3.2 Api调用接口
3.2.1 src\api\teacher.js 导出的默认对象中,添加ID查询方法 getById和更新方法 update
getById(id) {
return request({
url: `/teacher?id=${id}`,
method: 'get'
})
},
update(teacher) {
return request({
url: '/teacher',
method: 'put',
data:teacher
})
}
3.2.2 在 src\views\teacher\index.vue 中的 handleEdit 方法做如下修改:
handleEdit(id) {
// console.log('edit', id);
this.handleAdd();
teacherApi.getById(id).then(response => {
const resp = response.data;
if (resp.flag) {
this.teacher = resp.data;
}
})
},
3.2.3 修改对话框中的确认按钮点击事件
<el-button
type="primary"
@click=" teacher._id === null ? addData('teacherForm') :
updateData('teacherForm')"
>确 定</el-button><!-- 通过判断id是否为空来进行新增功能或者编辑功能 -->
3.2.4 提交更新数据
updateData(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
teacherApi.update(this.teacher).then(response => {
const resp = response.data;
if (resp.flag) {
this.fetchData();//刷新列表数据
this.dialogFormVisible = false;//关闭窗口
this.$message({
message: resp.message,
type: 'success'
})
} else {
this.$message({
message: resp.message,
type: 'warning'
})
}
})
} else {
return false;
}
})
},
修改成功:
四、教师管理-删除
4.1 nodejs添加接口
4.1.1 教师删除接口
//?根据id删除一条教师信息(delete方法)
router.delete('/teacher', function (req, res) {
// console.log(req.body);
Teacher.findByIdAndRemove(req.body.id, function (err) {
if (err) {
return res.status(500).json({
code: 3000,
flag: false,
message: 'server error'
})
}
return res.status(200).json({
code: 2000,
flag: true,
message: '删除教师信息成功'
})
})
})
4.2 Api调用接口
4.2.1 src\api\teacher.js 导出的默认对象中,添加 deleteById 方法
deleteById(id) {
return request({
url: `/teacher`,
method: 'delete',
data: { id }
})
}
4.2.2 在 src\views\teacher\index.vue 中的 handleDele 方法做如下修改:
handleDelete(id) {
// console.log('delete', id);
this.$confirm('确认删除这条数据吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {//点击`确定`
teacherApi.deleteById(id).then(response => {
this.$message({
type: response.data.flag ? 'success' : 'error',
message: response.data.message
});
if (response.data.flag) {
this.fetchData();//将数据库中新的数据再获取一遍
}
})
}).catch(() => {//点击`取消`
this.$message({
message: '已取消删除',
type: 'info'
})
});
},
成功删除: