前言
随着技术的不断发展,前端工程师也被赋予了越来越多的职责。不再是从前只需要切个图,加个 css 样式就能完成任务的切图仔了。接下来这篇文章,完成一个简单的登录注册,能让你快速上手,成为一个‘小全栈工程师’,here we go!
koa 快速开始
安装
因为 node.js v7.6.x 已经完全支持 async/await 语法,所以请保证 node 的版本在 7.6 以上
推荐一个 node 的多版本管理工具:nvm。如何安装这里不再赘述,网上的教程有很多
https://github.com/creationix…
// 初始化 package.json
npm init
// 安装 koa2
npm install koa
一个 hello world
新建一个 index.js,敲上以下代码
//index.js
const Koa = require(‘koa’)
const app = new Koa()
app.use(async (ctx, next) => {
ctx.response.body = ‘ 你好,我是内地吴彦祖 ’
})
app.listen(3333, ()=>{
console.log(‘server is running at http://localhost:3333’)
})
在我们的命令行敲上
node index.js
就可以看到运行结果啦:
几个核心概念
中间件好基友 ctx 和 next
在上面的代码中,我们可以看到 app.use 后面使用了 2 个参数,ctx 和 next,下面我们介绍一个这哥俩到底干嘛的
ctx
ctx 作为上下文使用,Koa 将 node 的 request, response 对象封装进一个单独对象。即 ctx.request、ctx.response。Koa 内部又对一些常用的属性或者方法做了代理操作,使得我们可以直接通过 ctx 获取。比如,ctx.request.url 可以写成 ctx.url。
next
next 参数的作用是将处理的控制权转交给下一个中间件
经典的洋葱图概念能很好的解释 next 的执行,请求从最外层进去,又从最里层出来。我们看一个例子
const Koa = require(‘koa’)
const app = new Koa()
app.use(async (ctx, next)=>{
let startTime = new Date().getTime()
await next()
let endTime = new Date().getTime()
console.log(` 此次的响应时间为:${endTime – startTime}ms`)
})
app.use(async (ctx, next) => {
console.log(‘111, 然后 doSomething’)
await next()
console.log(‘111 end’)
})
app.use(async (ctx, next) => {
console.log(‘222, 然后 doSomething’)
await next()
console.log(‘222 end’)
})
app.use(async (ctx, next) => {
console.log(‘333, 然后 doSomething’)
await next()
console.log(‘333 end’)
})
app.listen(3333, ()=>{
console.log(‘server is running at http://localhost:3333’)
})
看一下运行结果:
如果将‘222’函数的 next() 去掉的话,会发生什么呢?
可以看到,后面的‘333’中间件直接不执行了。所以中间件的顺序对 next 的执行有很大的影响
路由 koa-router
我们常用 koa-router 来处理 URL
安装
npm i koa-router –save
看一个例子:
const Koa = require(‘koa’)
const app = new Koa()
const Router = require(‘koa-router’)
const router = new Router()
router.get(‘/’, async (ctx, next) => {
ctx.body = ‘ 你好,我这里是 index 页 ’
})
router.get(‘/user’, async (ctx, next) => {
ctx.body = ‘ 你好,我这里是 user 页 ’
})
router.get(‘/error’, async (ctx, next) => {
ctx.body = ‘ 你好,我这里是 error 页 ’
})
app.use(router.routes())
app.listen(3333, ()=>{
console.log(‘server is running at http://localhost:3333’)
})
koa-router 也支持嵌套写法,通过一个总路由装载所有子路由,也非常的方便。看一个例子:
const Koa = require(‘koa’)
const app = new Koa()
const Router = require(‘koa-router’)
// 子路由 1
let oneRouter = new Router()
oneRouter.get(‘/’, async (ctx, next) => {
ctx.body = ‘ 你好,我这里是 oneRouter 页 ’
})
// 子路由 2
let twoRouter = new Router()
twoRouter.get(‘/’, async (ctx, next) => {
ctx.body = ‘ 你好, 我这里是 twoRouter 页 ’
}).get(‘/home’, async (ctx , next) => {
ctx.body = ‘ 你好, 我这里是 home 页 ’
})
// 装载所有子路由
let indexRouter = new Router()
indexRouter.use(‘/one’,oneRouter.routes(), oneRouter.allowedMethods())
indexRouter.use(‘/two’,twoRouter.routes(), twoRouter.allowedMethods())
app
.use(indexRouter.routes())
.use(indexRouter.allowedMethods())
app.listen(3333, ()=>{
console.log(‘server is running at http://localhost:3333’)
})
看一下运行结果:
获取请求数据
koa-router 提供了常见的 .get .put .post .del 接口来处理各种需求。实际开发中我们用的比较多的是 get 和 post,我们来看看 get 例子:
const Koa = require(‘koa’)
const app = new Koa()
const Router = require(‘koa-router’)
const router = new Router()
router.get(‘/data’, async (ctx , next)=> {
let url = ctx.url
// 从 ctx 的 request 中拿到我们想要的数据
let data = ctx.request.query
let dataQueryString = ctx.request.querystring
ctx.body = {
url,
data,
dataQueryString
}
})
app.use(router.routes())
app.listen(3333, ()=>{
console.log(‘server is running at http://localhost:3333’)
})
在浏览器里输入 http://localhost:3333/data?user=wuyanzu&id=123456 , 可以看到运行结果
可以看到区别,.query 返回的结果是对象,而.querystring 返回的是字符串,这个很好理解。(chrome 插件显示成 json 格式)
如果遵从 RESTful 规范, 比如请求要以 ‘/user/:id’ 的方式发出的话,我们可以用下面的例子来获取到想要的数据
添加代码
router.get(‘/data/:id’, async (ctx, next) => {
// 也从 ctx 中拿到我们想要的数据,不过使用的是 params 对象
let data = ctx.params
ctx.body = data
})
浏览器运行 http://localhost:3333/data/4396 看到结果
接下来我们看看 post 的例子
我们常用的请求 post,它的数据是放在 body 当中的。这个时候就推荐一个非常常用且好用的中间件 -koa-bodyparser
首先安装
npm i koa-bodyparser –save
然后我们在刚才的代码里添加
router.get(‘/post’, async (ctx, next) => {
// 模拟一段提交页面
let html = `
<form action=”/post/result” method=”post”>
<p> 你长的最像哪位明星 </p>
<input name=”name” type=”text” placeholder=” 请输入名字:”/>
<br/>
<p> 输入一段你知道的车牌号 </p>
<input name=”num” type=”text” placeholder=” 请输入车牌号:”/>
<br/>
<button> 确定不改了哦 </button>
</form> `
ctx.body = html
})
router.post(‘/post/result’, async (ctx, next) => {
// 我们可以从 ctx 的 request.body 拿到提交上来的数据
let {name, num} = ctx.request.body
if (name && num) {
ctx.body = `hello,你最像的明星是:${name},ch 你知道的车牌号是:${num}`
} else {
ctx.body = ‘ 啊哦~ 你填写的信息有误 ’
}
})
看一下运行结果
cache
koa 操作 cookie 是非常方便的,也是从上下文 ctx 中获取。
ctx.cookies.get(name, [options]) 读取上下文请求中的 cookie
ctx.cookies.set(name, value, [options]) 在上下文中写入 cookie
在我们刚才的 post 请求的代码中加入:
router.post(‘/post/result’, async (ctx, next) => {
// 我们可以从 ctx 的 request.body 拿到提交上来的数据
let {name, num} = ctx.request.body
if (name && num) {
ctx.body = `hello,你最像的明星是:${name},ch 你知道的车牌号是:${num}`
ctx.cookies.set(
‘xunleiCode’,num,
{
domain: ‘localhost’, // 写 cookie 所在的域名
path: ‘/post/result’, // 写 cookie 所在的路径
maxAge: 10 * 60 * 1000, // cookie 有效时长
expires: new Date(‘2018-09-17’), // cookie 失效时间
httpOnly: false, // 是否只用于 http 请求中获取
overwrite: false // 是否允许重写
}
)
} else {
ctx.body = ‘ 啊哦~ 你填写的信息有误 ’
}
})
看一下运行结果:
koa 操作 session 的话,需要用到 koa-session,????:
const session = require(‘koa-session’)
app.keys = [‘some secret hurr’];
const CONFIG = {
key: ‘koa:sess’, //cookie key (default is koa:sess)
maxAge: 86400000, // cookie 的过期时间 maxAge in ms (default is 1 days)
overwrite: true, // 是否可以 overwrite (默认 default true)
httpOnly: true, //cookie 是否只有服务器端可以访问 httpOnly or not (default true)
signed: true, // 签名默认 true
rolling: false, // 在每次请求时强行设置 cookie,这将重置 cookie 过期时间(默认:false)
renew: false, //(boolean) renew session when session is nearly expired,
};
app.use(session(CONFIG, app));
小结
在涉及到自己没有接触过的领域时,我一直推崇先看看要怎么玩,等自己会玩了以后,再看看“究竟”怎么玩。我们通过上面的代码和描述,已经对 koa 及 node 有一个初步的印象和概念。下篇文章我们会有中间件的拆分,单元测试,记录日志,管理规范等。让我们共同成长!
广而告之
本文发布于薄荷前端周刊,欢迎 Watch & Star ★,转载请注明出处。
欢迎讨论,点个赞再走吧 。◕‿◕。 ~