学了一段时间的 js 了,忽然想实践一下。正好公司有个小的项目要作,就顺手拿 Koa2 来作了。真是不作不知道,作了想不到。踩了一堆新手坑。javascript
在知道 Koa2 以前,我也了解过 Express,惋惜并无实战用过。后来你们都说 Koa 是一个比 Express 更牛X的东西,因而在好(做)奇(死)心做祟下,直接去用 Koa2 了。后来证实的确是做死,本来用 PHP 一天就能写完东西,愣是让我搞了三天。html
最近 Node.js V8 发布了,原生支持 async
和 await
调用了,因此直接把 Node.js 升级了一下。java
根据 Koa2 的教程,安装很简单,我是使用的 yarn 的(还真是比 npm 快)。node
yarn add koa
默认就装了 Koa 2.2。而后装完了,其实我是一脸懵逼的,文档上说这样用。git
const Koa = require('koa') const app = new Koa() // response app.use(ctx => { ctx.body = 'Hello Koa' }) app.listen(3000)
我照着代码写了下来,的确成功了。但是,难不成我要把全部的逻辑写在 app.use
里?github
我感受我受到了惊吓,吓得我赶忙往下看文档。原来 Koa2 是一个中间件模型。app.use
能够有不少,每个 app.use
会注册一个中间件,这个中间件是具体作事情的。每一个中间件是依次执行的。一个经典的洋葱图能够解释这一切。npm
那么,上面的实例就能够改形成这样。json
app.use(async (ctx, next) => { await next() ctx.body = 'Hello Koa' })
按照上面的洋葱头,以心为单位,next的两侧的语句分别在洋葱的左侧和右侧进行执行,颇像 Laravel
的中间件。bash
就这样,我知道了,全部的操做没必要写在同一个 app.use
里。但是,下一个问题来了,我要把全部的逻辑都写再一个文件里?说好的 MVC 呢?没有 MVC 也叫作框架?Are you kidding me?(好吧后来发现原来 Koa2 并非一个装置作网站的框架)app
既然没有 MVC,那就本身动手丰衣足食吧。
首先要处理的就是路由的问题。不过,因为是第一次用这货写项目,时间紧,(伪)任务重,看了文档后发现,原来还有一个中间件列表的连接,里面有各类开源的中间件。我想大家必定隔着屏幕都能听到我发出杠铃般的笑声了。有一个中间件很是棒,叫作 koa-router。这货是这么用的。
var Koa = require('koa') var Router = require('koa-router') var app = new Koa() var router = new Router() router.get('/', function (ctx, next) { // ctx.router available }); app.use(router.routes())
虽然是把逻辑和 app.use
分开了,可是,好像仍是没有解决刚才的问题。说好的 MVC 也没有出现。因而我再去找了找,竟然没有 Controller
的中间件。我一下就懵逼了,玩脱了?还有一天啊个人宝贝儿。通过我半秒钟的慎重思考,我仍是用 koa-router
本身实现一个控制器吧。
const fs = require('fs') function addRoutes(router, routes) { for (let route in routes) { switch (route.method) { case: 'post': router.post(route.uri, route.fn) console.log(`Register post url: ${route.uri}`) break case: 'get': router.get(route.uri, route.fn) console.log(`Register get url: ${route.uri}`) break default: console.log(`Invalid url: ${route}`) } } } function addControllers(router) { let files = fs.readdirSync(__dirname + '/controllers') let controllerFiles = files.filter(f => { return f.endsWith('.js') }) for (let controllerFile in controllerFiles) { console.log(`process controller: ${controllerFile}...`) let routes = require(__dirname + '/controllers') addRoutes(router, routes) } } module.exports = () => { let router = require('koa-router')() addControllers(router) return router.routes() }
我经过在 controllers
文件夹中,建立若干 js
文件来做为 Controller
来使用。这里稍微参考了下 廖雪峰的文章。
而后,咱们只须要在 controllers
文件夹中添加合适的文件就能够了。例如咱们添加一个文件叫作 chart.js
,而后这样写代码。
let hello = async (ctx, next) => { ctx.body = 'Hello the fucking world!' } module.exports = [ { method: 'get', uri: 'hello', fn: hello, } ]
最后再在 app.js
注册中间件便可。
除此以外,咱们还须要可以处理 ctx
里的内容,由于它里面存储的是原始的内容。仍是因为时间紧,任(填)务(坑)重(急),我用了 koa-bodyparser。
const bodyParser = require('koa-bodyparser') app.use(bodyParser())
这里要提醒的是,这货必定要放在处理路由中间件的前面。
MVC
的 C
已经解决了,接下来就要解决 M
的问题了。这里我用的是 Sequelize。这个 ORM
和大多数的 ORM
都差很少,因此在这里此次没有踩到什么坑。我在根目录下新建了一个 config.js
的配置文件,而后新建了 model.js
用来定义模型。
const Sequelize = require('sequelize') const config = require('./config').databases ... module.exports = { //models }
视图,我是使用了一个中间件叫作 koa-view。因为它使用的是 Nunjucks 模板引擎,对于写 PHP
的我相对熟悉一点。
const view = require('koa-view') const app = Koa() app.use(view(__dirname + '/views'))
//controller let Hello = (ctx, next) => { ctx.render('hello', datas) }
只要在 'views' 文件夹中定义相对应的 html 文件便可。
此次的尝试,终于在个人修修补补中,搞出了一个简陋的 MVC
模型。赶在了 deadline 前完成,真是一波三折啊。学习新技术,就是这样,要实践嘛= =下面给出个人项目目录做参考
koa2/ | +- controllers/ | | | +- chart.js | ... | +- static/ | | | +- js/ | ... | | | +- style/ | | | +- img | ... | +- views/ | | | +- game.html | ... | +- app.js | +- config.js | +- controller.js | +- model.js | +- package.json | +- yarn.lock | +- node_modules/
菜鸟做品,若有错误请指正,不胜感激。
若是你喜欢个人文章,那就请我喝杯奶茶吧~