基于node.js的express框架的图书管理功能
Posted 浮华夕颜
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于node.js的express框架的图书管理功能相关的知识,希望对你有一定的参考价值。
之前的图书管理功能的数据是存放在json文件中的,通过读取json文件的内容渲染到页面上,每次读取都要遍历整个文件,当数据量大时很不方便,把数据存放在数据库中才是正确的做法。
1.操作数据库的基本功能
在mysql中新建一个数据库book,新建一张book的表用来存放图书的数据信息,将id值设为自增。
利用数据库自增功能有一个问题:在执行删除操作后,再添加数据时,id会出现间隔现象,如下图:
数据库搭建好后,创建一个项目测试一下数据库操作的一些基本功能:
新建一个文件夹mydb
准备一个入口文件:index.js
初始化该项目:npm init -y
安装需要的依赖的包:
npm install mysqljs/mysql
①插入数据
/** * 插入数据 */ //加载数据库驱动 const mysql = require(\'mysql\'); //创建数据库链接 const connection = mysql.createConnection({ host: \'localhost\', //数据库所在的服务器的域名或者IP地址 user: \'root\', //登录数据库的账号 password: \'password\', database: \'book\' //数据库的名称book,注意这里不是链接的名称,我创建的链接的名称为mybook }); //执行连接操作 connection.connect(); //使用mysql第三方包简化了insert操作,?用来填充数据,只需要提供一个对象 let sql = \'insert into book set ?\' //用来插入的数据 let data = { name: \'明朝那些事\', author: \'当年明月\', category: \'文学\', description: \'明朝的历史\' } //操作数据库 connection.query(sql,data,(err,results,fields) => { if(err) return; //console.log(results); if(results.affectedRows == 1){ console.log(\'数据插入成功\'); } }); //关闭数据库 connection.end();
②更新数据
/** * 更新数据 */ //加载数据库驱动 const mysql = require(\'mysql\'); //创建数据库链接 const connection = mysql.createConnection({ host: \'localhost\', //数据库所在的服务器的域名或者IP地址 user: \'root\', //登录数据库的账号 password: \'password\', database: \'book\' //数据库的名称book,注意这里不是链接的名称,我创建的链接的名称为mybook }); //执行连接操作 connection.connect(); let sql = \'update book set name=?,author=?,category=?,description=? where id=?\' //用来更新的数据 let data = [\'浪潮之巅\',\'吴军\',\'计算机\',\'IT巨头的兴衰史\',6]; //操作数据库 connection.query(sql,data,(err,results,fields) => { if(err) return; //console.log(results); if(results.affectedRows == 1){ console.log(\'数据更新成功\'); } }); //关闭数据库 connection.end();
③删除数据
/** * 删除数据 */ //加载数据库驱动 const mysql = require(\'mysql\'); //创建数据库链接 const connection = mysql.createConnection({ host: \'localhost\', //数据库所在的服务器的域名或者IP地址 user: \'root\', //登录数据库的账号 password: \'password\', database: \'book\' //数据库的名称book,注意这里不是链接的名称,我创建的链接的名称为mybook }); //执行连接操作 connection.connect(); let sql = \'delete from book where id=?\' //用来删除的数据 let data = [6]; //操作数据库 connection.query(sql,data,(err,results,fields) => { if(err) return; //console.log(results); if(results.affectedRows == 1){ console.log(\'数据删除成功\'); } }); //关闭数据库 connection.end();
④查询数据
/** * 操作数据库基本步骤 */ //加载数据库驱动 const mysql = require(\'mysql\'); //创建数据库链接 const connection = mysql.createConnection({ host: \'localhost\', //数据库所在的服务器的域名或者IP地址 user: \'root\', //登录数据库的账号 password: \'password\', database: \'book\' //数据库的名称book,注意这里不是链接的名称,我创建的链接的名称为mybook }); //执行连接操作 connection.connect(); let sql = \'select * from book\' let data = null; //操作数据库 connection.query(\'select 1+1 as solution\',(err,results,fields) => { if(err) return; console.log(results[0]); }); //关闭数据库 connection.end();
上述的增删改查的代码有很多重复性,可以将以上功能封装为一个通用的api文件db.js:
/** * 封装操作数据库的通用API */ const mysql = require(\'mysql\'); exports.base = (sql,data,callback) => { //创建数据库链接 const connection = mysql.createConnection({ host: \'localhost\', //数据库所在的服务器的域名或者IP地址 user: \'root\', //登录数据库的账号 password: \'password\', database: \'book\' //数据库的名称book,注意这里不是链接的名称,我创建的链接的名称为mybook }); //执行连接操作 connection.connect(); //操作数据库(数据库操作也是异步的,异步不同通过返回值来处理,只能通过回调函数) connection.query(sql,data,(err,results,fields) => { if(err) throw err; callback(results); }); //关闭数据库 connection.end(); }
测试该api:
/** * 测试通用API */ const db = require(\'./db.js\'); //插入操作 let sql = \'insert into book set ?\'; let data = { name: \'笑傲江湖\', author: \'金庸\', category: \'文学\', description: \'武侠小说\' }; db.base(sql,data,(result) => { console.log(result); }); //更新操作 let sql = \'update book set name=?,author=?,category=?,description=? where id=?\'; let data = [\'天龙八部\',\'金庸\',\'文学\',\'武侠小说\',5]; db.base(sql,data,(result) => { console.log(result); }); //删除操作 let sql = \'delete from book where id=?\' let data = [7]; db.base(sql,data,(result) => { console.log(result); }); //查询操作 let sql = \'select * from book where id = ?\'; let data = [8]; db.base(sql,data,(result) => { console.log(result); });
2.通过一个小的登陆验证功能来测试前后端+数据库一起的功能:
后台逻辑代码login.js:
/** * 登陆验证(前端+后端+数据库) */ const express = require(\'express\'); const bodyParser = require(\'body-parser\'); const db = require(\'./db.js\'); const app = express(); //启动bodyParser这个API来处理参数,处理表单提交的 app.use(bodyParser.urlencoded({extended:false})); app.use(express.static(\'./public\')); app.post(\'/check\',(req,res) => { let param = req.body; console.log(param); let sql = \'select count(*) as total from user where username=? and password=?\'; let data = [param.username,param.password]; db.base(sql,data,(result) => { console.log(result); if(result[0].total == 1){ res.send(\'login success!\'); }else{ res.send(\'login failure!\'); } }); }); app.listen(3000,() => { console.log(\'running...\'); });
前端页面代码login.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>登录</title> </head> <body> <form action="http://localhost:3000/check" method="POST"> 用户名:<input type="text" name="username"><br> 密码:<input type="password" name="password"><br> <input type="submit" value="登录"> </form> </body> </html>
3.重构图书管理功能,使数据从数据库中获取
将操作数据库的通用api文件db.js拷贝到mybook项目下,还需要安装mysql的api
(注意:由于desc字段在数据库中是关键字,不能使用,所以把该字段名称改为description,之前的.art文件里用到的desc字段名称全部要改过来,否则执行过程中会报错)
只需修改service.js业务模块中的功能:
/** * 业务模块 */ const data = require(\'./data.json\'); const path = require(\'path\'); const fs = require(\'fs\'); const db = require(\'./db.js\'); /* //自动生成图书编号(自增) let maxBookCode = () => { let arr = []; data.forEach(item => { arr.push(item.id); }); return Math.max.apply(null,arr); } //把内存数据写入到文件 let writeDataFile = (res) => { //需要把内存中的数据写入文件 //JSON.stringify(data)仅传data一个参数的话,data.json文件是压缩形式的 fs.writeFile(path.join(__dirname,\'data.json\'),JSON.stringify(data,null,4),(err) => { if(err){ res.send(\'server err\'); } //文件写入成功之后重新跳转到主页面 res.redirect(\'/\'); }); } */ //渲染主页面 exports.showIndex = (req,res) => { let sql = \'select * from book\'; //从数据库中获取内容 db.base(sql,null,(result) => { //数据库获取的内容只能通过回调函数来得到 res.render(\'index\',{list:result}); }) //res.render(\'index\',{list:data}); } //跳转到添加图书的页面 exports.toAddBook = (req,res) => { //render将会根据views中的模板文件进行渲染,渲染的是空对象{} res.render(\'addBook\',{}); } //添加图书保存数据 exports.addBook = (req,res) => { //获取表单数据 let info = req.body; let book = {}; for (const key in info) { book[key] = info[key]; } let sql = \'insert into book set ?\' db.base(sql,book,(result) => { if(result.affectedRows == 1){ //添加成功后跳转到主页面 res.redirect(\'/\'); } }); /* book.id = maxBookCode()+1; data.push(book); //需要把内存中的数据写入文件 writeDataFile(res); */ } //跳转到编辑页面 exports.toEditBook = (req,res) => { let id = req.query.id; let sql = \'select * from book where id=?\'; let data = [id]; db.base(sql,data,(result)=>{ //注意:必须使用result[0]获取数据才能渲染到页面上,因为得到的resul结果集是一个数组,不是对象,渲染不了 res.render(\'editBook\',result[0]); }); /* let book = null; data.forEach((item)=>{ if(id == item.id){ book = item; //break; //forEach循环中不能有break,用return终结即可 return; } }); //render将会根据views中的模板文件进行渲染,渲染的是对应图书的完整信息 res.render(\'editBook\',book); */ } //编辑图书更新数据: //1.先查询出对应的数据并渲染到页面上 //2.然后再提交表单,再重新保存,写入文件 //编辑的时候要告诉服务器编辑的是哪条数据 exports.editBook = (req,res) => { //报错:为什么总是跳转到addBook的页面? 问题已解决:editBook.art页面的action路径错写成\'/addBook\',改成\'/editBook\'就可以正常运行 //获取表单的数据 let info = req.body; let sql = \'update book set name=?,author=?,category=?,description=? where id=?\'; let data = [info.name,info.author,info.category,info.description,info.id]; db.base(sql,data,(result) => { if(result.affectedRows == 1){ //更新成功后跳转到主页面 res.redirect(\'/\'); } else{ res.send(\'edit failure\'); } }); /* //覆盖原有的数据 data.forEach((item)=>{ if(info.id == item.id){ for (const key in info) { item[key] = info[key]; } return; } }); //需要把内存中的数据写入文件 writeDataFile(res); */ } //删除图书信息 exports.deleteBook = (req,res) => { //先获取到传过来的id let id = req.query.id; let sql = \'delete from book where id=?\'; let data = [id]; db.base(sql,data,(result) => { if(result.affectedRows == 1){ //删除成功后跳转到主页面 res.redirect(\'/\'); } }); /* data.forEach((item,index)=>{ if(item.id == id){ //删除数组的一项数据 data.splice(index,1); } return; }); //需要把内存中的数据写入文件 writeDataFile(res); */ }
以上是关于基于node.js的express框架的图书管理功能的主要内容,如果未能解决你的问题,请参考以下文章
Express - 基于 Node.js 平台的 web 应用开发框架
node.js基于express框架搭建一个简单的注册登录Web功能