项目目标:
1)熟练掌握ajax的使用 (*****)
2)熟悉前后端数据交互(***)
3)熟悉elementui 框架的使用(***)
4)熟悉vue的简单使用(***)
5)了解后端增删改查的逻辑
6)对整个项目的前后端结构和逻辑都有一个认识。
难点:分页(后端)模糊查询(后端)
DAY01需求:
A 搭建项目环境
1 使用express搭建项目环境
express smms -e
2 进入项目根目录 一次性安装所有依赖
cnpm i
3 监听端口 启动服务器
a) 打开app.js文件
app.listen(666, () => {
console.log('服务器启动成功...端口:666')
})
b) 启动服务器
nodemon app
B 前端资源文件都放入public, 集成elementui和vue.js
1 搭建前端目录结构,准备资源文件
images: 图片
js: 脚本
styles: 样式
libs:第三方库
elementui:
css: 样式文件
fonts: 字体文件(css需要引用它,注意路径!)
js: js脚本(依赖vue.js)
vue: vue.min.js
jquery: jquery.min.js
2 新建一个测试页面 测试环境是否搭建成功
注意:主要测试elementui是否可以使用。
C 登录页面的布局实现
1 登录页面表单
2 水平和垂直居中
1) 子绝父相
2) left right top bottom 都设置为0
3) margin: auto
D 表单的基本验证:
1 data里面有两份数据
1) 双向数据绑定 主要用来取值
loginForm: {
username: '', // 用户名
password: '', // 密码
confirmPassword: '' // 确认密码
}
2) 验证规则的数据
rules: {
// 验证用户名
username: [
{required: true, message: '请输入用户名', trigger: 'blur'}, // 非空验证
{min: 5, max: 12, message: '用户名长度在 5 到 12 个字符', trigger: 'blur'} // 长度验证
],
// 验证密码
password: [
{required: true, message: '请输入密码', trigger: 'blur'}, // 非空验证
{min: 6, max: 12, message: '密码长度在 6 到 12 个字符', trigger: 'blur'} // 长度验证
],
// 验证确认密码 (自定义验证规则)
confirmPassword: [
{ validator: checkPass, trigger: 'blur' } // 自定义验证函数
],
}
说明:
在return之前 自己写的验证函数
let 验证函数的名字 = (rules, value, callback) => {
// 对value判断
if (value === '') {
// 给出提示信息 输入框边框变红色 有一个 x
callback(new Error('不能为空'))
} else if (value.length < 6 || value.length > 18) {
// 给出提示信息 输入框边框变红色 有一个 x
callback(new Error('长度必须在6 - 18 位之间'))
} else {
// 成功 输入框边框变绿色 有一个√
callback()
}
}
rules: {
要验证的字段: [
{required: true, message: '提示信息', trigger: '触发方式'}, // 非空验证
{min: 5, max: 12, message:'提示信息', trigger: '触发方式'}, // 长度验证
{validator: 自己写的验证函数的名字, trigger: '触发方式'}
]
}
2 提交表单方法
submitForm(formName) {
// $refs能够把用 ref属性声明的dom 都收集在一个对象里面
this.$refs[formName].validate((valid) => {
// 如果valid是true 证明整个表单前端验证全部通过 允许发送给后端了
if (valid) {
// 收集用户输入的用户名和密码
let username = this.loginForm.username;
let password = this.loginForm.password;
// 构造ajax 把用户名和密码发送给后端(等待 后端去数据库查询存不存在)
} else {
// valid是false 证明前端验证没有通过 不允许提交表单 不允许发给后端
console.log('error submit')
return false;
}
})
}
3 重置表单:
resetForm(formName) {
// 获取整个表单 调用重置方法
this.$refs[formName].resetFields(); // this.$refs[formName] ==> this.$refs.loginForm
}
E 后台首页页面的实现
D 添加账号页面的实现
F 用户列表页面的实现
DAY02:需求
准备工作:
1 数据库设计:
数据库名字:admin
表的名字:users
创建用户账号表:
create table `users` (
id int primary key auto_increment,
username varchar(50),
password varchar(32),
groups varchar(50),
ctime TIMESTAMP default CURRENT_TIMESTAMP
);
2 nodejs连接mysql数据库?
1)下载mysql模块
cnpm i mysql --save
2) 引入mysql模块
const mysql = require('mysql');
3) 创建连接
const connection = mysql.createConnection({
host : 'localhost', // 主机名
user : 'root', // 用户名
password : 'root', // 密码
database : 'admin' // 数据库的名字
})
4) 调用连接方法
connection.connect();
3 nodejs操作数据库
a) 定义sql语句
const sqlStr = 'sql语句';
b) 执行数据库操作
connection.query(sqlStr, (err, data) => {
if (err) {
throw err
} else {
// 根据data的各种情况判断
}
})
A 创建git共享仓库
B 公共导航的抽取
iframe 标签
<iframe name="iframe的名称" src="引入的需要在这个标签里面显示的页面url" width="宽度" height="高度">
// src引入的页面 会在这里显示
</iframe>
C) 添加账号功能实现 (***)
1 前端-填写表单,点击添加按钮 发送ajax给后端(把用户账号的数据发送给后端)
a) 用户填写表单 通过所有的前端验证 收集表单的数据(双向绑定)
b) 把这些数据 通过ajax的post方式,发送给后端
2 后端-接收请求,接收数据
a) get方式使用 req.query post方式使用req.body
3 后端-把数据的数据 存入数据库
a) 构造sql语句(插入数据的sql)
const sqlStr "sql的增删改查的语法"
b) 执行sql语句
connection.query(sqlStr, (err, data) => { })
4 后端-根据存入数据库的结果 返回给前端一些信息
成功:res.send({"errcode":1, "msg":"添加成功"})
失败:res.send({"errcode":0, "msg":"添加失败"})
5 前端-根据后端返回的信息 判断
成功:》》弹出添加成功》》跳转到账号列表
失败:弹出添加失败,呵呵!
D) 用户列表功能的实现 (***)
1 前端-在生命周期 created 里面 发送ajax 去请求所有用户列表的数据
2 后端-接收这个请求
3 后端-构造sql语句 去数据库查询所有数据
4 后端-根据查询结果判断
如果有错抛出错误
否则直接把查询的所有数据响应给前端
5 前端-接收到后端返回的所有数据,赋值给tableData, 触发页面表格渲染
a)注意: 需要保留this的指向 ajax里面的this不指向vue实例了。
E) 用户删除功能的实现(***)
1 前端-点击删除按钮 触发一个函数 把 id 传入
2 前端-在这个函数里面 发送一个删除的请求 把 id 传给后端
3 后端-接收这个请求,接收id
4 后端-构造sql,以id为条件 执行删除
a)const sqlStr = 'delete from users where id=10'
5 后端-执行sql语句(单条删除操作)
a)如果有错 抛出错误
b)如果没有错 根据结果判断
i) 如果受影响的行数 > 0, 返回给前端一些信息(删除成功的信息)
res.send({"errcode":1, "msg":"删除成功!"})
ii) 否则 返回给前端一些信息(删除失败的信息)
res.send({"errcode":0, "msg":"删除失败!"})
6 前端-接收后端返回的数据,判断
a) 如果成功 》》弹 出删除成功 》》刷 新页面
b) 如果失败 弹出删除失败
DAY03:需求
A 修改功能的实现
准备: 先写一个修改页面
1 把原来的这一条数据回显出来
1) 前端-点击修改按钮 触发一个函数 传入id
2) 前端-在这个函数里面,直接跳转到修改页面,把id传过去
3) 前端-在修改页面的生命周期 created里面, 获取id, 里面发送ajax,把这个id发送给后端
4) 后端-接收请求,接收id
5) 后端-根据id构造sql,去数据库把这条数据查询出来
a)如果有错 抛出错误
b)否则 直接把根据id查询出来的这一条数据(也就是要修改的数据)发送给前端
6) 前端-接收数据,一一对应的,回填在修改页面的表单里面。
2 把修改后的新数据,保存回去(根据原来的id)
1) 前端-点击修改按钮,触发 submitForm
2) 前端-如果前端所有验证通过,收集用户填写的新数据 和 一个原来的id
3) 前端-发送ajax请求,这这些新数据 和 一个原来的id 一起发送给后端
4) 后端-接收前端发送的修改后的新数据 和 一个原来的id
5) 后端-以id为条件 构造sql语句(修改操作)
a) update users set 字段名1=新的值1, 字段名2=新的值2 where id = 接收到的id
6) 后端-执行修改的sql语句,根据修改的结果 判断 返回给前端一些信息
a)如果有错 抛出错误
b)如果没有错 根据修改的结果数据判断
如果成功:返回成功的数据对象给前端
如果失败:返回失败的数据对象给前端
7) 前端-接收后端返回的信息 判断
a)成功: 》》弹 出对应的提示信息 》》跳 转到用户列表页面
b)失败: 弹出对应的提示信息
B 批量删除的实现
1 前端-给取消选中绑定事件 在事件里面实现取消选择
2 前端-给整个table绑定选中就会改变的selection-change事件类型,
触发一个函数handleSelectionChange,自定把选中的数据传入函数里面
3 前端-在这个函数里面,接收到这个值,把他赋值给一个属性(vue实例)
this.multipleSelection = val;
4 前端-给批量删除上绑定事件,在事件里面,获取 this.multipleSelection(里面保存了被勾选的数据)
5 前端-遍历数据 this.multipleSelection 把里面的id 获取出来,放入一个数组 (被选中的数据的id)
6 前端-构造ajax 把这些被选中的id们(数组)发送给后端
7 后端-接收请求 接收这个包含id们 的数组
8 后端-构造sql语句(in 子句),执行sql语句删除
1) 如果有错 抛出错误
2)否则 根据删除的结果数据 data 判断
a) 如果 成功(受影响行数 > 0) 返回成功的数据对象给前端
b) 否则 返回失败的数据对象给前端
9 前端-接收后端响应回来的数据 判断
1)如果成功 》》弹 出对应的提示信息 》》刷 新页面
2)如果失败 弹出对应的提示信息
C 登录功能实现
1 检查用户身份(用户名和密码是否正确,是否在数据库里面存在)
1)前端-前端验证通过,发送ajax请求给后端,把用户名和密码发送给后端
2)后端-接收请求,接收用户名和密码
3)后端-以用户名和密码 且 的关系,构造sql语句 执行sql语句查询数据库,判断
a)如果有错 抛出错误
b)否则 看数据是否存在 判断
如果存在返回成功(存在)的数据对象
否则返回失败(不存在)的数据对象
4)前端-根据后端响应的数据,判断
a)如果存在 》》弹 登录成功 》》跳 转到后台系统首页
b)如果不存在 弹 出请检查用户名或密码
2 检查用户是否已经登录(cookie)
cookie: 储存在用户本地终端(浏览器)上的数据
说明:就是由服务器端(后端)创建存储在浏览器(客户端、前端)上的一种追踪用户的技术。
nodejs操作cookie
增:设置:res.cookie(key, value); // res.cookie('username', 'admin')
删:清除cookie: res.clearCookie(key) // res.clearCookie('username')
改:修改cookie: res.cookie(key, newValue) // res.cookie('username', 'guest');
查:获取cookie: req.cookies.key // req.cookies.username;
具体步骤:
1)后端-如果登录成功 设置cookie (在登录成功的路由里面设置)
2)前端-每一个页面 都发送一个请求 (为了检测cookie是否存在)
<script src="/users/checkIsLogin"></script>
3)后端-接收这个请求 获取cookie(从浏览器),检测是否存在
如果存在不作出任何操作(需要返回一些信息)
如果不存在返回弹窗请登录以后再操作跳转到登录页面
3 退出登录功能
1) 前端-点击退出系统,通过a标签发送一个get方式的请求
2) 后端-接收请求,清除cookie, 弹出对应提示, 跳转到登录页面
DAY04需求:
A 修改密码功能实现
1 验证旧密码
1)前端-写一个修改密码页面,实现前端的表单验证
2)前端-自定义旧密码的验证规则(旧密码正不正确 前端是不知道的 需要发送ajax去验证)
3)前端-在自定义的函数里面 直接发送ajax 把输入的旧密码的值 发送给后端
4)后端-接收旧密码,从cookies获取当前登录用户的id。
5)后端-根据id为条件,把当前用户数据查询出来,用查询出来的密码 和 接收到的旧密码比较
a)如果有错 抛出错误
b) 否则 判断
如果成功:返回成功的数据对象给前端
如果失败:返回失败的数据对象给前端
6)前端-根据后端响应结果判断
如果错误
使用callback(new Error('错误信息'))
如果正确
callback()
2 保存新密码(执行修改)
1) 前端-点击保存按钮 发送ajax 把新密码发送给后端
2)后端-接收新密码 从cookie获取 id
3)后端-以id为条件 构造sql语句(修改密码)
4)后端-执行sql语句,根据结果判断
如果成功:
清除cookie
返回成功的数据对象给前端
5)前端-根据后端响应的数据,判断
如果成功:》》填充修改密码成功》》跳转到登录页面
B 分页功能实现
分页思路分析:(后端分页)
后端分页需要什么条件呢?
1) 每页显示多少条 pageSize ? 从前端传过来,用户选择了以后就传过来
2)当前在第几页呢 currentPage ? 从前端传过来 用户点了哪个页码 就传给后端
3)后端查询所有数据 计算数据的总条数 发送给前端
4) 把当前用户想要的 对应页面的 数据 查询出来 发送给前端
sql查询条件:
n = (currentPage - 1)*pageSize
select * from users limit(n, pageSize)
结论:(*****)
前端需要给后台发送什么?
a) 页面尺寸pageSize
b) 当前页面 currentPage
后端需要给前端返回什么?
a)数据总条数据 (前端需要用来计算页码有多少)
b)对应页面的数据(点击第1页 就只返回第 1 页的数据 )
工作中:(常见分页)
前端:只需要给后端发送当前页码
后端:自己构造sql 把对应当前页码的数据返回。
分页步骤:
1 前端-使用分页组件 在对应的位置写上(账号列表页面)
2 前端-获取需要发送给后端的参数: pageSize(页面尺寸) currentPage(当前页)
3 前端-改造页面里面请求数据的函数 getAllUsers
需要把前端的参数传入这个函数一起发送给后端(改成按照分页请求数据 而不是一次请求所有数据)
4 后端-接收请请求,接收参数 pageSize 和 currentPage
5 后端-构造sql 查询全局数据,计算出数据总条数
const sqlStr = 'select * from users';
connection.query(sqlStr, (err, data) => {
if (err) {
throw err
} else {
// 计算数据总条数
let totalcount = data.length;
}
})
6 后端-构造sql 排序然后 按照分页的条件查询 查询出对应页码的数据
let n = (currentPage - 1)*pageSize
sqlStr += ` order by ctime desc limit ${n}, ${pageSize}`
connection.query(sqlStr, (err, data) => {
if (err) {
throw err
} else {
// 按照分页查询的数据的结果(前端传过来哪一页就是对应页码的数据)
let pageData = data;
// 把数据总条数 和 对应页码的数据 一起发送给前端
res.send({"totalcount": totalcount, "pageData": pageData})
}
})
7 前端-接收数据(数据是一个对象: {"totalcount":数据总条数, "pageData":对应当前页码的数据})
把数据赋值给data里面 对应的字段
DAY05需求:
A 分页功能完善
B 登录显示当前登录用户功能完善
C 商品列表模块商品添加实现
D 商品管理模块实现
E 高级查询
1 前端-点击查询按钮,触发一个函数, 在这个函数里面,
收集查询的两个参数(分类名称 和 关键字(商品名称 或 条形码)) 发送给后端
2 前端-发送ajax 把 分类名称 和 关键字 发送给后端
3 后端-接收请求,接收参数(分类名称 和 关键字)
4 后端-根据参数 构造sql语句 按照条件查询 ? 怎么写sql? (****)
5 后端-执行sql,把查询的结果返回给前端
6 前端接收返回结果 赋值给 tableData, 渲染表格