摘要:本打算教一步步實現(xiàn),因為要解釋的太多了,所以先簡化成版本,從實現(xiàn)部分功能到閱讀源碼,希望能讓你好理解一些。
本打算教一步步實現(xiàn)koa-router,因為要解釋的太多了,所以先簡化成mini版本,從實現(xiàn)部分功能到閱讀源碼,希望能讓你好理解一些。
希望你之前有讀過koa源碼,沒有的話,給你鏈接
router最重要的就是路由匹配,我們就從最核心的入手
router.get("/string",async (ctx, next) => { ctx.body = "koa2 string" }) router.get("/json",async (ctx, next) => { ctx.body = "koa2 json" })
我們希望
路徑訪問 /string 頁面顯示 "koa2 string"
路徑訪問 /json 頁面顯示 "koa2 json"
先分析1.我們需要一個數(shù)組,數(shù)組里每個都是一個對象,每個對象包含路徑,方法,函數(shù),傳參等信息
這個數(shù)組我們起個名字叫stack
const stack = []
2.對于每一個對象,我們起名叫l(wèi)ayer
我們把它定義成一個函數(shù)
function Layer() { }
我們把頁面比喻成一個箱子,箱子是對外的,箱子需要有入口,需要容納。把每一個router比作放在箱子里的物件,物件是內(nèi)部的
定義兩個js頁面,router.js做為入口,對于當前頁面的訪問的處理,layer.js包含開發(fā)者已經(jīng)約定好的規(guī)則
router.js
module.exports = Router; function Router(opts) { // 容納layer層 this.stack = []; };
layer.js
module.exports = Layer; function Layer() { };
我們在Router要放上許多方法,我們可以在Router內(nèi)部掛載方法,也可以在原型上掛載函數(shù)
但是要考慮多可能Router要被多次實例化,這樣里面都要開辟一份新的空間,掛載在原型就是同一份空間。
最終決定掛載在原型上
方法有很多,我們先實現(xiàn)約定幾個常用的吧
const methods = [ "get", "post", "put", "head", "delete", "options", ];
methods.forEach(function(method) { Router.prototype[method] = function(path,middleware){ // 對于path,middleware,我們需要把它交給layer,拿到layer返回的結(jié)果 // 這里交給另一個函數(shù)來是實現(xiàn),我們叫它register就是暫存的意思 this.register(path, [method], middleware); // 因為get還可以繼續(xù)get,我們返回this return this }; });實現(xiàn)layer的溝通
Router.prototype.register = function (path, methods, middleware) { let stack = this.stack; let route = new Layer(path, methods, middleware); stack.push(route); return route };
這里我們先去寫layer
const pathToRegExp = require("path-to-regexp"); function Layer(path, methods, middleware) { // 把方法名稱放到methods數(shù)組里 this.methods = []; // stack盛放中間件函數(shù) this.stack = Array.isArray(middleware) ? middleware : [middleware]; // 路徑 this.path = path; // 對于這個路徑生成匹配規(guī)則,這里借助第三方 this.regexp = pathToRegExp(path); // methods methods.forEach(function(method) { this.methods.push(method.toUpperCase()); // 綁定layer的this,不然匿名函數(shù)的this指向window }, this); }; // 給一個原型方法match匹配返回true Layer.prototype.match = function (path) { return this.regexp.test(path); };
回到router層
定義match方法,根據(jù)Developer傳入的path, method返回 一個對象(包括是否匹配,匹配成功layer,和匹配成功的方法)
Router.prototype.match = function (path, method) { const layers = this.stack; let layer; const matched = { path: [], pathAndMethod: [], route: false }; //循環(huán)寄存好的stack層的每一個layer for (var len = layers.length, i = 0; i < len; i++) { layer = layers[i]; //layer是提前存好的路徑, path是過來的path if (layer.match(path)) { // layer放入path,為什么不把path傳入,一是path已經(jīng)沒用了,匹配了就夠了,layer含有更多信息需要用 matched.path.push(layer); //如果methods什么也沒寫,或者如果方法里含有你的過來的方法,那么把layer放入pathAndMethod if (layer.methods.length === 0 || ~layer.methods.indexOf(method)) { matched.pathAndMethod.push(layer); // 路徑匹配,并且有方法 if (layer.methods.length) matched.route = true; } } } return matched; };
給Developer一個方法
app.use(index.routes())
這里不考慮傳多個id,和多次匹配情況,拿到匹配的函數(shù)
Router.prototype.routes = function(){ var router = this; const dispatch = function dispatch(ctx, next) { const path = ctx.path const method = ctx.method const matched = router.match(path, ctx.method); if (!matched.route) return next(); const matchedLayers = matched.pathAndMethod // 先不考慮多matchedLayers多stack情況 return matchedLayers[0].stack[0](ctx, next); } return dispatch }
此時一個迷你koa-router已經(jīng)實現(xiàn)了
讀源碼 需求實現(xiàn) 實現(xiàn)匹配方法名匹配,路徑匹配,還要滿足動態(tài)參數(shù)的傳遞
并且還要給很懶的開發(fā)者一個router.all()
也就是說不用區(qū)分方法了
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/102805.html
摘要:問題描述在使用作為路由遇到了一個優(yōu)先級問題如下代碼在訪問時路由會優(yōu)先匹配到路由返回這個問題就很尷尬了項目空閑下來去翻看源碼終于找到了原因問題原因的源碼并不長和兩個文件加起來共一千多行代碼建議可以結(jié)合這篇文章閱讀其中造成這個問題的原因 問題描述 在使用Koa-router作為路由遇到了一個優(yōu)先級問題.如下代碼 // routerPage.js file const router = re...
摘要:第三篇,有關(guān)生態(tài)中比較重要的一個中間件第一篇源碼閱讀第二篇源碼閱讀與是什么首先,因為是一個管理中間件的平臺,而注冊一個中間件使用來執(zhí)行。這里寫入的多個中間件都是針對該生效的。 第三篇,有關(guān)koa生態(tài)中比較重要的一個中間件:koa-router 第一篇:koa源碼閱讀-0 第二篇:koa源碼閱讀-1-koa與koa-compose koa-router是什么 首先,因為koa是一個管...
摘要:代碼結(jié)構(gòu)執(zhí)行流程上面兩張圖主要將的整體代碼結(jié)構(gòu)和大概的執(zhí)行流程畫了出來,畫的不夠具體。那下面主要講中的幾處的關(guān)鍵代碼解讀一下。全局的路由參數(shù)處理的中間件組成的對象。 代碼結(jié)構(gòu) showImg(https://segmentfault.com/img/remote/1460000007468236?w=1425&h=1772); 執(zhí)行流程 showImg(https://segmentf...
摘要:四路由注冊構(gòu)造函數(shù)首先看了解一下構(gòu)造函數(shù)限制必須采用關(guān)鍵字服務器支持的請求方法,后續(xù)方法會用到保存前置處理函數(shù)存儲在構(gòu)造函數(shù)中初始化的和屬性最為重要,前者用來保存前置處理函數(shù),后者用來保存實例化的對象。 一、前言 ??Koa為了保持自身的簡潔,并沒有捆綁中間件。但是在實際的開發(fā)中,我們需要和形形色色的中間件打交道,本文將要分析的是經(jīng)常用到的路由中間件 -- koa-router。 ??...
路由koa-router——MVC 中重要的環(huán)節(jié):Url 處理器 ?? iKcamp 制作團隊 原創(chuàng)作者:大哼、阿干、三三、小虎、胖子、小哈、DDU、可木、晃晃 文案校對:李益、大力萌、Au、DDU、小溪里、小哈 風采主播:可木、阿干、Au、DDU、小哈 視頻剪輯:小溪里 主站運營:給力xi、xty 教程主編:張利濤 視頻地址:https://www.cctalk.com/v/151...
閱讀 2885·2021-10-18 13:33
閱讀 840·2019-08-30 14:20
閱讀 2619·2019-08-30 13:14
閱讀 2512·2019-08-29 18:38
閱讀 2878·2019-08-29 16:44
閱讀 1205·2019-08-29 15:23
閱讀 3466·2019-08-29 13:28
閱讀 1909·2019-08-28 18:00