web开发框架、koa和koa-router、模板引擎、MVC
web开发
Web框架:提供了一套开发和部署网站的方式,提供web服务的。Express,Sails.js,koa,Meteor,DerbyJS,Total.js,restify
ORM框架:对象-关系映射,通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。Sequelize,ORM2,Bookshelf.js,Objection.js
模板引擎:基于模板配合数据构造出字符串输出的一个组件,能够编写几个HTML模板,并且用实际数据来渲染模板并获得最终的HTML输出,还可以避免输出恶意脚本。Jade,EJS,Swig,Nunjucks,doT.js
测试框架、自动化构建工具:解决应用在浏览器的UI和功能上兼容性问题,并对网站资源进行优化,可以大大提高我们的工作效率。测试框架包括:Mocha,Expresso,Unit.js,Karma。构建工具有:Grunt,Gulp,Webpack。
koa
koa对httpm模块
进行了封装。最新版本简化了异步的写法,结合Promise、async、箭头函数来实现异步。
使用npm加载koa。
使用koa来创建web服务:
// 导入koa,和koa 1.x不同,在koa2中,我们导入的是一个class,因此用大写的Koa表示:
const Koa = require('koa');
// 创建一个Koa对象表示web app本身:
const app = new Koa();
app.use(async (ctx, next) => {
console.log('第一1');
await next();
console.log('第一2');
});
app.use(async (ctx, next) => {
console.log('第二1');
await next();
console.log('第二2');
});
// 对于任何请求,app将调用该异步函数处理请求:
app.use(async (ctx, next) => {
console.log('第三1 ' + ctx.request.URL);
await next();
ctx.response.type = 'text/html';
ctx.response.body = '<h1>Hello, koa2!</h1>';
console.log('第三2' );
});
// 在端口3000监听:
app.listen(3000);
console.log('app started at port 3000...');
async函数
、await next()
方法:使用app.ues()
来注册async函数,将每一async函数称为middleware
,将这些middleware
组合起来形成一条链。使用await next()
来调用下一个middleware
,当没有调用await next()
时下一个middleware
是不会执行的。
打印顺序:
第一1
第二1
第三1 http://localhost:3000/
第三2
第二2
第一2
处理post请求:在package.json
中引入koa-bodyparser
依赖来解析request
中的body
,解析后会自动绑定到ctx.request.body
中。
koa-router
对于任何请求都会走app.use()
方法,处理不同的url访问,可能要写成这样:
app.use(async (ctx, next) => {
if (ctx.request.path === '/index') {
ctx.response.body = 'index page';
} else {
await next();
}
});
app.use(async (ctx, next) => {
if (ctx.request.path === '/login') {
ctx.response.body = 'login page';
} else {
await next();
}
});
app.use(async (ctx, next) => {
if (ctx.request.path === '/login/success') {
ctx.response.body = 'login success';
} else {
await next();
}
});
显然这种写法很心痛,koa-router
库就是解决这个问题的,我们可以npm
下把它引入到项目中。
koa-router
负责处理URL的映射。
URL <===> controller。所有处理url的的异步函数 async (ctx, next) => {}
,都可以按照功能创建对应controller.js
文件,并将这些controller.js
放至controllesr
文件夹下,就可以达到根据URL Router
进行模块化。
在app.js中的代码可以简化成:
const router = require('koa-router')();
// add url-route:
router.get('/index', async (ctx, next) => {
var name = ctx.params.name;
ctx.response.body = 'index page';
});
router.get('/login', async (ctx, next) => {
ctx.response.body = 'login page';
});
router.get('/login/success', async (ctx, next) => {
ctx.response.body = 'login success';
});
app.use(router.routes());
模板引擎
模板引擎 + 输入的对象 => html
// 模板引擎
function render (name) {
return `${name}, 生日快乐!`
}
// 生成的html
var html = render({ name: '王大吉' });
引擎模板的好处:转义
、格式化、简单逻辑。
Nunjucks
是模板引擎
之一。
基本使用:以上返回html字符串代码大致是这样的,以返回个人主页为例:
const nunjucks = require('nunjucks');
function createEnv(path, opts) {
...
return env;
}
var env = createEnv('views', {
...
});
// 返回的html (需要绘制的界面,传入的对象)
var s = env.render('hello.html', { name: ${name}});
结合koa使用:在koa调用某一个异步函数来处理一个url时,使用Nunjucks
输出需要显示的html,并赋值给response.body
。
需要给ctx
对象绑定一个render(view, model)
方法,这样controller中就可以调用这个方法来渲染模板。
Nunjucks
提供的功能强大的tag,编写条件判断、循环等功能。
模板的继承:网站的结构实际上是类似的,头部、尾部都是固定格式,只有中间页面部分内容不同。所以可以写一个基础的网页框架base.html
<html><body>
{% block header %} <h3>Unnamed</h3> {% endblock %}
{% block body %} <div>No body</div> {% endblock %}
{% block footer %} <div>copyright</div> {% endblock %}
</body>
子模块hello.html可以定义:
<!-- 继承base.html -->
{% extends 'base.html' %}
<!-- header -->
{% block header %}
<body>
<h1>{{ header }}</h1>
<p>{{ name }}</p>
</body>
{% endblock %}
<!-- body -->
{% block body %}
<body>
<h1> body -- {{body}}</h1>
{% for f in fruits %}
<p>{{ f }}</p>
{% endfor %}
</body>
{% endblock %}
<!-- footer -->
{% block footer %}
<body>
<h1> footer -- {{footer}} </h1>
{% for f in fruits %}
<p>{{ f }}</p>
{% endfor %}
</body>
{% endblock %}
如果model数据为:
var renderdata = {
name: name ,
fruits: ['apple', 'o', '1'],
header: '这是头部',
body: '这是内容',
footer: '这是尾部'
};
执行env.render('hello.html', renderdata);
后返回的html的代码为:
<html><body>
<body>
<h1>这是头部</h1>
<p>koa</p>
</body>
<body>
<h1> body -- 这是内容</h1>
<p>apple</p>
<p>o</p>
<p>1</p>
</body>
<body>
<h1> footer -- 这是尾部 </h1>
<p>apple</p>
<p>o</p>
<p>1</p>
</body>
</body>
最终显示的效果图:
通过Nunjucks将原来直接输出字符串的方式,改成通过指定参数通过赋值,用在指定的模板上,并渲染成HTML,然后输出给浏览器,用户就可以看到渲染后的页面。性能方面,Nunjucks是同步IO读取模板文件,但是有缓存机制,所以渲染返回字符串的效率是比较高的。
MVC
现在项目的目录结构:
50231545298803_.pic_hd.jpg
MVC分别代表的含义和作用:
M:model,可以理解成js对象。
V:view,通过简单的参数替换,输出html代码。
C:controller,负责一些业务逻辑,网络请求、判断用户名是否存在,存储个人信息等。
View是html,可以使用现成的Bootstrap的css框架,因为在生产和测试环境下加载css的方式是不一样的,要判断下环境:
// 判断是否是生产环境
const isProduction = process.env.NODE_ENV === 'production';
if (! isProduction) {
// 判断当前请求url是否是加载的是静态文件
let staticFiles = require('./static-files');
app.use(staticFiles('/static/', __dirname + '/static'));
}
使用static字符串来区分是否是静态文件的请求,使用Bootstrap的css框架:
<!-- Bootstrap core CSS -->
<link href="static/css/bootstrap.min.css" rel="stylesheet">
在生产环境下,静态文件是由部署在最前面的反向代理服务器(如Nginx)处理的,Node程序不需要处理静态文件。而在开发环境下,我们希望koa能顺带处理静态文件,否则,就必须手动配置一个反向代理服务器,这样会导致开发环境非常复杂。
/login
登录界面:
登录成功或失败后,界面跳转至/signin
界面:
网友评论