学习链接
Simple User Management System - Nodejs, Express, MySQL & Handlebars - Raddy
- 作者:Raddy
- 日期:2021.02.12
Navicat如何操作数据库
什么是handlebars?
- 可以动态修改html的内容!有类似vue的v-for,和v-if的语句,不过写法不一样。
- express-handlebars - npm (npmjs.com)
- Handlebars 的基本用法_handlebars 语法_高先生的猫的博客-CSDN博客
学习目标
技术栈:express、mysql、handlebars。
前端搭建页面,使用handlebars模板引擎,结合bootstrap一起实现展示页面,具体的实现功能有:
- 搜索用户信息 - 结合路由,返回数据库内容
- 删除用户信息
- 创建用户信息
- 修改用户信息
后端利用express的路由信息进行管理,和mysql进行交互,完成对于用户的增删改查功能的实现。
搭建流程
系统的具体实现,可以分为五个步骤
- 数据录入 - mysql数据库的创建!
- 搭建环境 - node.js环境和数据库信息输入
- 配置路由 - 路由信息以及数据连接
- 创建页面 - handlebars编写页面以及bootstrap框架
- 增删改查 - 用户信息修改、删除、查找、增加!
系统实现
1. 数据录入
使用的软件是navicat,点击查询,输入sql语句,点击运行,创建项目所需的表!
输入内容
- 它会在mysql数据中,创建usermanagement_tut表,以及其中的字段信息!
CREATE TABLE `mysql`.`usermanagement_tut` (
`id` INT NOT NULL AUTO_INCREMENT,
`first_name` VARCHAR (45) NOT NULL,
`last_name` VARCHAR (45) NOT NULL,
`email` VARCHAR (45) NOT NULL,
`phone` VARCHAR (45) NOT NULL,
`comments` TEXT NOT NULL,
`status` VARCHAR (10) NOT NULL DEFAULT 'active',
PRIMARY KEY (`id`)
)
还有表中的值,同样写入表中
INSERT INTO `usermanagement_tut`
(`id`, `first_name`, `last_name`, `email`, `phone`, `comments`, `status`) VALUES
(NULL, 'Amanda', 'Nunes', 'anunes@ufc.com', '012345 678910', '', 'active'),
(NULL, 'Alexander', 'Volkanovski', 'avolkanovski@ufc.com', '012345 678910', '', 'active'),
(NULL, 'Khabib', 'Nurmagomedov', 'knurmagomedov@ufc.com', '012345 678910', '', 'active'),
(NULL, 'Kamaru', 'Usman', 'kusman@ufc.com', '012345 678910', '', 'active'),
(NULL, 'Israel', 'Adesanya', 'iadesanya@ufc.com', '012345 678910', '', 'active'),
(NULL, 'Henry', 'Cejudo', 'hcejudo@ufc.com', '012345 678910', '', 'active'),
(NULL, 'Valentina', 'Shevchenko', 'vshevchenko@ufc.com', '012345 678910', '', 'active'),
(NULL, 'Tyron', 'Woodley', 'twoodley@ufc.com', '012345 678910', '', 'active'),
(NULL, 'Rose', 'Namajunas ', 'rnamajunas@ufc.com', '012345 678910', '', 'active'),
(NULL, 'Tony', 'Ferguson ', 'tferguson@ufc.com', '012345 678910', '', 'active'),
(NULL, 'Jorge', 'Masvidal ', 'jmasvidal@ufc.com', '012345 678910', '', 'active'),
(NULL, 'Nate', 'Diaz ', 'ndiaz@ufc.com', '012345 678910', '', 'active'),
(NULL, 'Conor', 'McGregor ', 'cmcGregor@ufc.com', '012345 678910', '', 'active'),
(NULL, 'Cris', 'Cyborg ', 'ccyborg@ufc.com', '012345 678910', '', 'active'),
(NULL, 'Tecia', 'Torres ', 'ttorres@ufc.com', '012345 678910', '', 'active'),
(NULL, 'Ronda', 'Rousey ', 'rrousey@ufc.com', '012345 678910', '', 'active'),
(NULL, 'Holly', 'Holm ', 'hholm@ufc.com', '012345 678910', '', 'active'),
(NULL, 'Joanna', 'Jedrzejczyk ', 'jjedrzejczyk@ufc.com', '012345 678910', '', 'active')
表格创建完毕,共有六个字段
- id - 唯一id
- first_name - 名
- last_name - 姓
- email - 邮箱
- phone - 电话
- comments - 评论
- status - 状态
表格信息展示,用于程序获取、修改等
2. 搭建环境
初始化项目
- 创建一个文件夹,输入
npm init -y
,得到package.json
安装所需的库
npm install mysql express dotenv express-handlebars
配置scripts属性
创建app.js文件
app.js中的内容
**启动项目命令 **
npm run start
- 启动项目,并且开始监听5000端口
app.js中的完整内容
补充信息:
3. 配置路由
配置路由是案例的核心内容,通过对不同路由的响应,展示对应的内容,数据的传递,也是通过路由信息来实现的。
在app.js文件中,我们配置了app.use("/", routers)
,所有在根路径(/
)下的路由,都会通过routers进行处理。
创建server文件夹,以及routes文件夹和controllers文件
- 在routes文件下的user.js处理路由信息的跳转
- 在controllers文件下的userController.js处理路由信息的数据传递
- 它们的关系是user.js引入userController.js,做到了路由信息和数据信息的分离!
user.js中的内容
- 这里的
router.get("/", userController.view)
,对应localhost:5000/ - 这里的
router.get("/adduser", userController.view)
,对应localhost:5000/adduser - 它们的根路径,在app.js中设置了,即
/
- 处理路由的内容,都放在userController里,
- 在user.js中,主要就是处理get 和post请求,分配路由信息
userController.js中的内容
- 连接mysql数据库
- 根据路由信息,处理不同的功能,
- 这里的exports.view,将获取到的信息(数据库查表),展示到页面上!共做了两步操作
- 查询语句:
SELECT * FROM usermanagement_tut WHERE status = 'active'
- 页面渲染:
res.render("home", {rows, removedUser});
,这是用handlebars模板写的home页面,利用res.render
将home页面渲染到页面中,同时也将找到的数据传递到模板中,实现了页面的更新!
- 查询语句:
其他功能,在后文 增删改查中详述。
4. 创建页面
main.hbs
利用handlebars创建页面,我们创建views文件夹,接着创建layouts文件夹以及main.hbs,这是页面渲染的入口
写个hello
页面显示出来了!
在main.hbs中引入bootstarp组件,
- 共三个,bootstrap样式,bootstrap图标,bootstrap的js文件
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1"
crossorigin="anonymous"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.3.0/font/bootstrap-icons.css"
/>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js"
integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW"
crossorigin="anonymous"
></script>
在bootstrap官网,选个nav导航栏组件
修改一下样式,修改跳转路由,这样可以将请求的数据拦截,在这个过程中,获取后端数据!
目前效果
在main.hbs中输入{{{body}}}(三个括号),它存放的是home.hbs的内容。这样页面的入口的和其他页面就分离了!
在home.hbs中写入hello...
页面效果,组件分离!
home.hbs
home.hbs写了三个样式
- 提示信息 - (删除用户信息时候提示)
- 添加按钮 - (跳转到添加用户页)
- 展示列表 - (列表展示,后台获取信息)
- 提示信息
handlebars模板引擎使用render函数进行渲染,在渲染的同时,可以传递信息,实现页面的动态展示!
- 添加按钮
添加用户按钮,点击跳转到对应的页面(同时渲染在浏览器中)
- 展示列表
add-user.hbs
共三个部分
- 导航信息 - 用于返回主页
- 提示信息 - 添加成功显示!
- 用户表单 - 使用user-form.hubs,复用同样页面
submit按钮的跳转路由是 /adduser
,express会对提交的信息做处理(写入数据库)
user-form.hbs
可以复用的页面,放在partials下!
user-form.hbs内容
edit-user.hbs
同add-user.hbs,不过传入当前用户的信息!会在user-form.hbs中显示!(这里的this就派上用场了! - this.first_name!)
view-user.hbs
展示用户信息!
5. 增删改查
有了页面,那么页面中的数据是怎么传入的呢?
- 当我们跳转到对应的路由,会利用express的中间件(app.use),处理请求和响应之间的数据
- 在这个过程中,根据发送请求的路由信息,获取对应的数据内容,然后渲染对应的handlebars模板(比如main.hbs, home.hbs, add-user.hbs等),同时传入我们获取到的数据,就实现了页面的动态展示!
- 使用handlebars模板引擎的好处
- 增加页面的复用性 - 页面拆分
- 可以使用条件、循环等语句 - 页面展示逻辑
- 连接了前端和后端信息,直接渲染出来 - 不需要处理dom
好,再来梳理一下路由的交互方式
在app.js中,当我们访问根目录时,会执行routes方法(这里放着我们处理的路由信息)
处理路由的方式
-
- 将路由分为两个部分,一个负责处理请求路由,一个负责响应路由(渲染页面 + 传递数据库信息)
- user.js - 处理请求路由
- userController.js - 负责响应路由
user.js内容
- 引入userController.js,处理请求信息
路由与交互行为分析!
- 路由的跳转,与用户的行为(事件)密不可分!
- 这里的路由信息,并不遵循restful api(资源),更多的是语义化的路由信息
// 获取所有信息 -(在home页面,列表展示 - 页面初始化!)
router.get("/", userController.view);
// 搜索框 输入信息,发起post请求
router.post("/", userController.find);
// 点击添加按钮(跳转页面到user-add.hbs,开始创建)
router.get("/adduser", userController.form);
// 点击提交按钮(创建完毕)
router.post("/adduser", userController.create);
// 点击修改按钮(跳转页面到user-edit.hbs,开始修改)
router.get("/edituser/:id", userController.edit);
// 点击提交按钮(修改完毕)
router.get("/edituser/:id", userController.update);
// 点击用户展示按钮 - (跳转页面到view-user.hbs,展示当前用户的所有信息)
router.get("/viewuser/:id", userController.viewall);
// 点击删除按钮 - (删除当前用户,并给出提示信息)
router.get("/:id", userController.delete);
相关学习资料:
get 和 post学习链接
- GET/POST 请求区别详解(接口测试实战) - 腾讯云开发者社区-腾讯云 (tencent.com)
- get请求
- get请求显示在url上,不安全
- 有长度限制
- 请求数据会完整留在历史记录里
- 只能进行url编码
- 被浏览器主动cache(缓存)
- post请求
- 请求信息在request body中
- 长度没有限制
- 相对于get来说,安全一点(http中,都是明文显示)
- post的参数,不会留在历史记录里
- 支持多种编码方式
- 浏览器不会主动cache
- HTTP协议中的两种发送请求的方法,本质是TCP连接
- GET产生一个TCP数据包(全部);POST产生两个TCP数据包(先发送header,再发送data)。
node js中的req.body,req.query,req.params取参数 - Diamond蚊子 - 博客园 (cnblogs.com)
- 获取get路由信息 - req.params.userid
- 获取post信息 - req.body.search
- req.params包含路由参数(在URL的路径部分),而req.query包含URL的查询参数(在URL的?后的参数)。
mysql模糊查询
- MySQL——模糊查询(LIKE关键字与通配符:百分号%和下划线_的使用和理解)——(运用场景+通俗易懂)_like和%和__一颗剽悍的种子的博客-CSDN博客
- like - 关键字
- ? - 占位符,可替换查找内容
- % - 通配符,任意0或多个字符
- [] - 和?配合
详细分析下,每个路由的执行内容
userController.view
home.hbs,获取所有列表信息
userController.find
头部导航栏,输入框,输入名 或姓,查找信息,由home.hbs列表呈现
userController.form
返回add-user.hbs添加用户页面!不需要查询数据库
userController.create
将所有的表单数据,插入(INSERT)到数据库
userController.edit
通过url获取需要修改的用户的id信息,从数据库获取该用户的所有信息
userController.update
继续由edit-user页面展示,并发送修改成功的信息
共做两步操作
- 使用UPDATE,更新数据信息
- 使用SELECT,获取最新数据
userController.viewall
获取当前用户的所有信息,SELECT查询url中的id即可
userController.delete
删除用户,通过状态来控制,这样即保留了用户,又不会显示在页面中!删除成功,重定向,会再次获取全部信息。
总结
记完整录了前后交互过程,对于前端路由和后端路由有了进一步的理解。
前端路由主要通过get和post来传递数据,后端路由通过拦截前端路由的数据,进行处理后,再返回给前端展示。
后端路由更多的涉及到用户行为和数据的关系。点击什么按钮,返回什么数据,还需要考虑到api的设计,如何处理get和post方法。
原作者其他关于node的教程,也非常棒!多多关注!
你是最好哒最俏哒 最妙哒最骄傲哒!