当我们使用Express作为服务端框架时,如果我们选择类似EJS的模板引擎来渲染前端页面,服务端往往会在响应http请求时调用res.render({options})将数据渲染到模板。我们会经常看到res.locals和app.locals对象,那么它们有什么作用呢?查看原代码://express/lib/response.jsres.render=functionrender(view,options,callback){varapp=this.req.app;var完成=回调;varopts=选项||{};varreq=this.req;变种自我=这个;//支持回调函数作为第二个参数if(typeofoptions==='function'){done=options;选择={};}//合并res.localsopts._locals=self.locals;//响应的默认回调done=done||function(err,str){if(err)returnreq.next(err);自我发送(海峡);};//渲染app.render(view,opts,done);};变量opts最初获取的是开发者代码中传入的options对象,即代码段中的opts._locals=self.locals;self指向res对象本身,也就是给最终渲染到模板中的变量加上一个对象属性。该属性的值为res.locals,然后调用app.render函数,传入opts对象。//express/lib/application.jsapp.render=functionrender(name,options,callback){varcache=this.cache;var完成=回调;varengines=this.engines;varopts=选项;varrenderOptions={};变量视图;//支持回调函数作为第二个参数if(typeofoptions==='function'){done=options;选择={};}//合并app.localsmerge(renderOptions,this.locals);//合并options._localsif(opts._locals){merge(renderOptions,opts._locals);}//合并选项merge(renderOptions,opts);//除非明确提供,否则设置.cacheif(renderOptions.cache==null){renderOptions.cache=this.enabled('viewcache');}//准备好缓存if(renderOptions.cache){view=cache[name];}//查看if(!view){varView=this.get('view');view=newView(name,{defaultEngine:this.get('viewengine'),root:this.get('views'),engines:engines});if(!view.path){vardirs=Array.isArray(view.root)&&view.root.length>1?'目录“'+view.root.slice(0,-1).join('”,“')+'”or“'+view.root[view.root.length-1]+'”':'directory"'+view.root+'"'varerr=newError('Failedtolookupview"'+name+'"inviews'+dirs);err.view=查看;返回完成(错误);}//初始化缓存if(renderOptions.cache){cache[name]=view;}}//rendertryRender(view,renderOptions,done);merge是一个第三方模块,可以很方便的合并两个对象。不难看出,这个函数在获取到最终的渲染变量对象时,再次合并了app.locals对象,开发者传入的对象res.render,res。locals对象和app.locals对象合并为最终渲染模板的材质。知道这个过程后,就很容易理解为什么在项目入口文件app.js中经常看到如下代码://设置站点全局常量app.locals.webGlobal={title:"",description:"",keywords:""}//设置是可变的,但每个模板总是需要一些模板变量app.use(function(req,res,next){res.locals._host=req.headers.host;res.locals._user=req.user;res.locals._url=req.url||req.originalUrl;res.locals._moment=moment;res.locals._enums=enums;next();});res.render传入的对象作为特定场景下特定页面的个性化可变信息数据。常量信息通常挂载在app.locals上,变量信息通常挂载在res.locals上。三者相辅相成,构成渲染模板的全部变量信息。
