项目记录
Table of Contents
生成Express项目
Node.js的安装在此跳过. 本项目在Node.js的基础上开始.
# 安装express npm install express-generator -g # 查看express命令选项 express -h # 创建项目 express --view=hbs healthy # 安装依赖 cd myapp npm install # 运行 npm start # 或者 DEBUG=healthy:* npm start # Linux, MacOS set DEBUG=healthy:* & npm start # Windows
此时可在浏览器中输入 http://localhost:3000 访问该应用.
目录结构
/bin: 用于应用的启动. /public: 放置静态资源. /routes: 放置路由. /views: 放置模板文件(html). app.js: 程序的入口文件
模板引擎
本项目使用 handlebars 模板引擎, 该模板引擎默认使用的模板文件的后缀名是 hbs, 因此 views子目录 中的文件全是 hbs 结尾的. 这边我们进行修改, 使模板引擎使用后缀名为 html 的文件作为模板文件.
修改根目录下的 app.js 文件, 加入以下几句话:
// 在开头添加如下代码
var hbs = require('hbs');
// 将 app.set('view engine', 'hbs'); 改成如下代码
app.set('view engine', 'html');
// 紧接上面一句, 添加如下代码
app.engine('html', hbs.__express);
并将 views 目录下的文件后缀名直接改成 html.
MySQL
以下通过一个简单的例子来说明如何将Express与MySQL整合起来.
创建表
创建一个简单的表, 表结构如下:
MySQL模块
在 package.json 的 dependencies 中新增以下配置:
"mysql":"latest"
执行 npm install.
目录结构
根据需要的功能, 在根目录再新建三个目录, 分别管理.
mkdir util # 工具 mkdir conf # 配置 mkdir dao # 与数据库交互(Data Access Object)
conf目录
新建配置文件, 编定MySQL数据库连接配置. emacs conf/db.js:
// MySQL数据库联接配置
module.exports = {
mysql: {
host: '127.0.0.1',
user: 'root',
password: '123456',
database:'healthy', // 前面建的user表位于这个数据库中
port: 3306
}
};
dao目录
该目录下需要新建两个文件. 第一个(userSqlMapping.js)的内容是对数据库中某个表进行操作的SQL语句. 第二个(userDao.js)的内容是获取前端传过来的数据, 通过SQL语句存到MySQL中.
emacs dao/userSqlMapping.js:
// CRUD SQL语句
var user = {
insert:'INSERT INTO user(id, name, age) VALUES(0,?,?)',
update:'update user set name=?, age=? where id=?',
delete: 'delete from user where id=?',
queryById: 'select * from user where id=?',
queryAll: 'select * from user'
};
module.exports = user;
emacs dao/userDao.js:
// 实现与MySQL交互
var mysql = require('mysql');
var $conf = require('../conf/db');
var $util = require('../util/util');
var $sql = require('./userSqlMapping');
// 使用连接池,提升性能
var pool = mysql.createPool($util.extend({}, $conf.mysql));
// 向前台返回JSON方法的简单封装
var jsonWrite = function (res, ret) {
if(typeof ret === 'undefined') {
res.json({
code:'1',
msg: '操作失败'
});
} else {
res.json(ret);
}
};
module.exports = {
add: function (req, res, next) {
pool.getConnection(function(err, connection) {
// 获取前台页面传过来的参数
var param = req.query || req.params;
// 建立连接,向表中插入值
// 'INSERT INTO user(id, name, age) VALUES(0,?,?)',
connection.query($sql.insert, [param.name, param.age], function(err, result) {
if(result) {
result = {
code: 200,
msg:'增加成功'
};
}
// 以json形式,把操作结果返回给前台页面
jsonWrite(res, result);
// 释放连接
connection.release();
});
});
}
};
util目录
emacs util/util.js:
// 提升性能
module.exports = {
extend: function(target, source, flag) {
for(var key in source) {
if(source.hasOwnProperty(key)){
flag ? (target[key] = source[key]) : (target[key] === void 0 && (target[key] = source[key]));
}
}
return target;
}
};
添加路由
emacs routes/users.js:
// 在文件开头添加以下代码
var userDao = require('../dao/userDao');
// 添加以下路由
// 增加用户
router.get('/addUser', function(req, res, next) {
userDao.add(req, res, next);
});
测试
为了方便, 前面实现的是get请求的add方法, 所以可以直接在浏览器中使用地址添加数据到数据库. http://localhost:3000/users/addUser?name=xyz&age=18
根据返回的内容, 判断是否成功. 如果成功, 在数据库中应该可以看到添加了一条新数据.
代码组织
路由都写在 routes 目录下, 然后通过 module.exports = router 将里面的处理方法导出.
在入口文件 app.js 中, 使用 var users = require('./routes/users') 这种语句, 将处理方法赋给 app.js 中的变量, 再使用 app.use('/path', middle) 将路径与处理方法绑定.
以后, 一级路径(如'/users'), 就在 app.js 中与相应的模块进行绑定, 而二级或者更高级的路径(如'/users/pinvon'), 就在路由 routes/users.js 中, 将具体的路径与相应的中间件进行绑定.
关于数据库, 对于数据库中的每一个表, 有一个相应的文件(如'dao/userSqlMapping.js')来编写所需要用到的SQL语句, 然后再有一个相应的文件(如'dao/userDao.js')来作为数据库和前端的中间处理程序. 即, 一个表会有两个对应的文件, 来实现对数据库的操作.
前后端数据传递
后端:
result = {
code: 200,
msg:'增加成功'
};
res.json(result);
前端:
success: function (data, status) {
if (status == 'success') {
console.log(data);
layer.msg('注册成功');
setTimeout(function () {
location.href = 'login';
}, 2000);
}
},
error: function (data, err) {
console.log(data);
alert('fail');
}
打印结果如下图所示:
可以根据 code 的值, 来判断下一步该怎么处理.
问题记录
- 注册时使用post方法提交数据, 在后台进入post对应的中间件处理, 将数据存储到数据库, 存储完成后回到post方法继续执行, 会进入到get方法, 而代码中没在post方法里面写明会渲染或重定向到get. 目前的方案是在get()中判断参数, 如果路径中带参数, 则不让渲染注册页面.
- Node.js的线程: 如果函数有回调函数, 该函数的返回值依赖于回调函数, 则函数的返回值一般不是我所预期的, 因为函数会先返回, 然后再去执行回调函数.
Generated by Emacs 25.x(Org mode 8.x)
Copyright © 2014 - Pinvon - Powered by EGO