学了一段时间的 js 了,突然想实践一下。正好公司有个小的项目要做,就顺手拿 Koa2 来做了。真是不做不知道,做了想不到。踩了一堆新手坑。
初次接触 Koa2
在知道 Koa2 之前,我也了解过 Express,可惜并没有实战用过。后来大家都说 Koa 是一个比 Express 更牛X的东西,于是在好(作)奇(死)心作祟下,直接去用 Koa2 了。后来证明的确是作死,原本用 PHP 一天就能写完东西,愣是让我搞了三天。
安装
最近 Node.js V8 发布了,原生支持 async
和 await
调用了,所以直接把 Node.js 升级了一下。
根据 Koa2 的教程,安装很简单,我是使用的 yarn 的(还真是比 npm 快)。
yarn add koa
默认就装了 Koa 2.2。然后装完了,其实我是一脸懵逼的,文档上说这样用。
const Koa = require('koa') const app = new Koa() // response app.use(ctx => { ctx.body = 'Hello Koa' }) app.listen(3000)
我照着代码写了下来,的确成功了。可是,难不成我要把所有的逻辑写在 app.use
里?
中间件
我感觉我受到了惊吓,吓得我赶紧往下看文档。原来 Koa2 是一个中间件模型。app.use
可以有很多,每一个 app.use
会注册一个中间件,这个中间件是具体做事情的。每个中间件是依次执行的。一个经典的洋葱图可以解释这一切。
那么,上面的实例就可以改造成这样。
app.use(async (ctx,next) => { await next() ctx.body = 'Hello Koa' })
按照上面的洋葱头,以心为单位,next的两侧的语句分别在洋葱的左侧和右侧进行执行,颇像 Laravel
的中间件。
就这样,我知道了,所有的操作不必写在同一个 app.use
里。可是,下一个问题来了,我要把所有的逻辑都写再一个文件里?说好的 MVC 呢?没有 MVC 也叫做框架?Are you kidding me?(好吧后来发现原来 Koa2 并不是一个装置做网站的框架)
既然没有 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
自己实现一个控制器吧。
Controller
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())
这里要提醒的是,这货一定要放在处理路由中间件的前面。
Model
MVC
的 C
已经解决了,接下来就要解决 M
的问题了。这里我用的是 Sequelize。这个 ORM
和大多数的 ORM
都差不多,所以在这里这次没有踩到什么坑。我在根目录下新建了一个 config.js
的配置文件,然后新建了 model.js
用来定义模型。
const Sequelize = require('sequelize') const config = require('./config').databases ... module.exports = { //models }
View
视图,我是使用了一个中间件叫做 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/
菜鸟作品,如有错误请指正,不胜感激。
如果你喜欢我的文章,那就请我喝杯奶茶吧~
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。