模块介绍express-autoload-router模块用于自动加载和注册路由。模块的基本使用步骤如下。安装模块$npminstallexpress-autoload-router构建路由程序,将路由程序文件放在特殊目录app/controllers下。格式上有两点需要注意:路由程序文件名必须是xxx_controller.js;路由程序中的动作函数/对象名称必须是yyyAction;$catapp/controllers/user_controller.js/***objectmode,multipleroutes放在一起*/module.exports={listAction:{method:["GET"],middlewares:[],handler:function(req,res){returnres.send("用户列表操作");}},getAction:{方法:["GET"],中间件:[],处理程序:function(req,res){returnres.send("usergetaction");}}};在主程序catapp.js中引入并加载路由$constexpress=require("express");constpath=require('path');constloadRouter=require('express-autoload-router');constapp=express();loadRouter(app,"/demo",path.join(__dirname,"app/controllers"));app.listen(3000,function(){console.log("监听3000端口!");});其中,loadRouter()函数第二个参数指定一级路由,第三个参数指定路由程序文件所在目录。该函数会调用app.METHOD()(此处METHOD被get、post等HTTP方法代替)注册对应的路由,路由URI为:/demo/xxx/yyy。例子$curl-XGEThttp://localhost:3000/demo/user/listuserlistAction路由程序文件路由程序文件中的yyyAction可以写成一个函数,也可以写成一个对象,两者是等价的。使用函数的基本写法如下://普通路由,访问方式:/demo/product/listmodule.exports.listAction=function(req,res){returnres.send("productlistaction");};由于节点。在js中,module.exports和exports是等价的,所以也可以写成://module.exports和exports是等价的exports.getAction=function(req,res){returnres.send("productgetaction");}另外,函数也可以简化://简化函数:将函数改为=>exports.simpleAction=(req,res)=>{returnres.send("productsimpleaction");};进一步简化函数://更简化的函数:将函数更改为=>,省略花括号//URL可以是大写或小写:/demo/product/moreSimple或/demo/product/moresimpleexports.moreSimpleAction=(req,res)=>res.send("productmoreSimpleaction");使用对象基本写法:module.exports.buyAction={method:["GET","POST"],middlewares:[],handler:function(req,res){returnres.send("产品购买操作");}};等价写法://另一种写法handlerexports.sellAction={method:["GET","POST"],middlewares:[],handler(req,res){returnres.send("productsellaction");}};indexActioni处理的注意事项indexAction中的索引不会成为路由的一部分。例如路由文件product_controller.js,有://默认路由,访问方式:/demo/productmodule.exports.indexAction=function(req,res){returnres.send("productindexaction");};//普通路由,访问方式:/demo/product/listmodule.exports.listAction=function(req,res){returnres.send("productlistaction");};其中listAction对应的路由是/demo/product/list,indexAction对应的路由是/demo/product。路由子目录(subrouting)假设controllers目录下有一个子目录subdir,里面有一个路由程序文件subroute_controller.js,如下:$catapp/controllers/subdirmodule.exports.listAction=function(req,res){returnres.send("subdir/subroutelistaction");};listAction对应的路由是/demo/subdir/subroute/list。可以看出,子目录也会成为路由的一部分。Action名称大小写问题Action函数/对象名称可以使用驼峰式,对应的URL可以使用驼峰式或全部小写。示例如下://URL大小写均可:/demo/product/moreSimple或/demo/product/moresimplemodule.exports.moreSimpleAction=function(req,res){returnres.send("productmoreSimpleaction");}源码分析原理遍历每个controller文件,通过express对象的app[method]()方法在其中注册Action函数或对象,实现路由绑定。不管Action是函数还是对象,都会构造三个参数:method、middlewares、handler,然后通过以下方法注册。app[方法](url,compose(middlewares,modifiedUrl),handler);基本语法for...in和for...of用于数组迭代示例:for...in用于数组迭代>letmembers=["Jay","Angela","Henry"];>typeof(members)'object'>for(letiinmembers){...console.log(i);...}012示例:for...of用于数组迭代>letmembers=["Jay","Angela","亨利"];>for(letmemberofmembers){...console.log(member);...}JayAngelaHenryfor...in和for...of的区别:for...in只能用来遍历Object类型的对象(包括数组)的属性;for...of可以用于任何可迭代对象,例如:数组、字符串等。需要注意的是,Object不是可迭代对象。示例:for...inforobjects>lethenry={"age":6,"height":120};>for(letiinhenry){...console.log(i);...}ageheight示例:for...of不能用于对象>lethenry={"age":6,"height":120};>for(letiofhenry){...console.log(i);...}TypeError:亨利不可迭代(函数迭代(){})();定义并调用函数示例:>(functionf(req,res){...console.log(req);...console.log(res);...})("req","res");reqres注意:本例中函数名f可以省略。内置对象-StringString.prototype.replace()-替换函数:使用字符串字面量或正则表达式进行子串替换。更常见的是使用正则表达式来替换。示例:字符串文字替换注意:此方法只会替换第一个匹配的子字符串。>“杰伊,杰伊!你在做什么?”.replace(“杰伊”,“亨利”)'亨利,杰伊!你在干什么?'示例:正则表达式替换(无全局和忽略选项)注意:该方法只会替换第一个匹配的子字符串。>“杰伊,杰伊!你在做什么?”.replace(/Jay/,"Henry")'亨利,杰伊!你在干什么?'示例:正则表达式替换(有global和ignore选项)注:global选项表示替换所有匹配的子串,ignore选项表示匹配子串时忽略大小写。>“杰伊,杰伊!你在做什么?”.replace(/Jay/gi,"Henry")'亨利,亨利!你在干什么?'示例:将\替换为/注意:本例中,C:\\Windows\\System32使用\\来表示一个真正存储的\,因为节点解释器会做一个转换,会写成url.replace(/\\/gi,"/");在实际的节点程序中。>"C:\\Windows\\System32".replace(/\\/gi,"/");'C:/Windows/System32'String.prototype.match()-搜索功能:对子串String使用正则表达式匹配并返回匹配结果数组。说明:正则表达式的全局选项,将决定匹配结果数组中是否携带附加属性。附加属性包括:index——匹配结果的起始位置,input——原始字符串,groups——捕获组数组。例子:当正则表达式不使用全局选项时,会返回额外的属性>"listAction".match(/Action$/)['Action',index:4,input:'listAction',groups:undefined]例子:正则表达式当使用全局选项时,不返回附加属性>"listAction".match(/Action$/gi)['Action']例:当正则表达式没有匹配结果时,返回null>"list".match(/Action$/gi)null内置对象-ArrayArray.isArray()-判断功能:判断给定值是否为数组。这个函数是一个静态函数。示例:Array返回true>Array.isArray([1,2,3]);true示例:对象返回false>Array.isArray({"name":"Henry"});falseArray.prototype.indexOf()-Find功能:查找指定元素并返回第一个索引。如果没有找到,返回-1。示例:如果找到指定元素,返回索引>["Jay","Angela","Henry"].indexOf("Henry");2示例:如果没有找到指定元素,返回-1>["杰伊","安吉拉","亨利"].indexOf("科比");-1内置对象-FunctionFunction.prototype.bind()标准库-o??sos.platform()功能:Node编译时返回操作系统平台名称。例子:在Mac系统上执行>letos=require("os");>os.platform();'darwin'例子:在CentOS系统上执行>letos=require("os");>os.platform()'linux'第三方库-glob.sync()库的作用:使用pattern模式匹配文件,支持shell下的pattern模式。glob.sync()函数:同步遍历文件夹下所有文件,返回匹配文件路径数组。示例:遍历app/controllers/目录下的所有controller文件,不递归遍历子目录>letglob=require("glob");>glob.sync(`app/controllers/*_controller.js`)['app/controllers/product_controller.js','app/controllers/user_controller.js']例子:遍历app/controllers/目录下的所有controller文件,递归遍历子目录(加一个**目录)>letglob=require("glob");>glob.sync(`app/controllers/**/*_controller.js`)['app/controllers/product_controller.js','app/controllers/subdir/subroute_controller.js','app/controllers/user_controller.js']参考资料express-autoload-router模块源码本文源码
