编写view

时间:2022-05-04 00:44:56

编写View

在编写View的时候,我们实际上是在编写HTML页。为了让页面看起来美观大方,使用一个现成的CSS框架是非常有必要的。我们用​​Bootstrap​​这个CSS框架。从首页下载zip包后解压,我们把所有静态资源文件放到​​/static​​目录下:

view-koa/
|
+- static/
|
+- css/ <- 存放bootstrap.css等
|
+- fonts/ <- 存放字体文件
|
+- js/ <- 存放bootstrap.js等

这样我们在编写HTML的时候,可以直接用Bootstrap的CSS,像这样:

<link rel="stylesheet" href="/static/css/bootstrap.css">

现在,在使用MVC之前,第一个问题来了,如何处理静态文件?

我们把所有静态资源文件全部放入​​/static​​目录,目的就是能统一处理静态文件。在koa中,我们需要编写一个middleware,处理以​​/static/​​开头的URL。

编写middleware

我们来编写一个处理静态文件的middleware。编写middleware实际上一点也不复杂。我们先创建一个​​static-files.js​​的文件,编写一个能处理静态文件的middleware:

const path = require('path');
const mime = require('mime');
const fs = require('mz/fs');

// url: 类似 '/static/'
// dir: 类似 __dirname + '/static'
function staticFiles(url, dir) {
return async (ctx, next) => {
let rpath = ctx.request.path;
// 判断是否以指定的url开头:
if (rpath.startsWith(url)) {
// 获取文件完整路径:
let fp = path.join(dir, rpath.substring(url.length));
// 判断文件是否存在:
if (await fs.exists(fp)) {
// 查找文件的mime:
ctx.response.type = mime.lookup(rpath);
// 读取文件内容并赋值给response.body:
ctx.response.body = await fs.readFile(fp);
} else {
// 文件不存在:
ctx.response.status = 404;
}
} else {
// 不是指定前缀的URL,继续处理下一个middleware:
await next();
}
};
}

module.exports = staticFiles;

​staticFiles​​是一个普通函数,它接收两个参数:URL前缀和一个目录,然后返回一个async函数。这个async函数会判断当前的URL是否以指定前缀开头,如果是,就把URL的路径视为文件,并发送文件内容。如果不是,这个async函数就不做任何事情,而是简单地调用​​await next()​​让下一个middleware去处理请求。

我们使用了一个​​mz​​的包,并通过​​require('mz/fs');​​导入。​​mz​​提供的API和Node.js的​​fs​​模块完全相同,但​​fs​​模块使用回调,而​​mz​​封装了​​fs​​对应的函数,并改为Promise。这样,我们就可以非常简单的用​​await​​调用​​mz​​的函数,而不需要任何回调。

所有的第三方包都可以通过npm官网搜索并查看其文档:

​https://www.npmjs.com/​

最后,这个middleware使用起来也很简单,在​​app.js​​里加一行代码:

let staticFiles = require('./static-files');
app.use(staticFiles('/static/', __dirname + '/static'));

注意:也可以去npm搜索能用于koa2的处理静态文件的包并直接使用。