当我们使用 Express 做服务端框架的时候,如果选择一种类似于 EJS 这种模板引擎渲染前端页面的时候,经常服务端在响应 http 请求的时候调用 res.render({options})
去向模板中渲染数据。
我们还会经常看到 res.locals 和 app.locals 这对象,那么他们到底是干什么的呢? 查看原代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 res.render = function render (view, options, callback ) { var app = this .req.app; var done = callback; var opts = options || {}; var req = this .req; var self = this ; if (typeof options === 'function' ) { done = options; opts = {}; } opts._locals = self.locals; done = done || function (err, str ) { if (err) return req.next(err); self.send(str); }; app.render(view, opts, done); };
变量 opts 初始时获得开发人员代码中传入的 options 对象,这段代码中的opts._locals = self.locals;
self 指向 res 对象自身,即又在最终渲染到模板中的变量里面增添了一个对象属性,该属性的值为 res.locals
紧接着调用到了 app.render
函数,并传入 opts 对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 app.render = function render (name, options, callback ) { var cache = this .cache; var done = callback; var engines = this .engines; var opts = options; var renderOptions = {}; var view; if (typeof options === 'function' ) { done = options; opts = {}; } merge(renderOptions, this .locals); if (opts._locals) { merge(renderOptions, opts._locals); } merge(renderOptions, opts); if (renderOptions.cache == null ) { renderOptions.cache = this .enabled('view cache' ); } if (renderOptions.cache) { view = cache[name]; } if (!view) { var View = this .get('view' ); view = new View(name, { defaultEngine: this .get('view engine' ), root: this .get('views' ), engines: engines }); if (!view.path) { var dirs = Array .isArray(view.root) && view.root.length > 1 ? 'directories "' + view.root.slice(0 , -1 ).join('", "' ) + '" or "' + view.root[view.root.length - 1 ] + '"' : 'directory "' + view.root + '"' var err = new Error ('Failed to lookup view "' + name + '" in views ' + dirs); err.view = view; return done(err); } if (renderOptions.cache) { cache[name] = view; } } tryRender(view, renderOptions, done);
merge 是一个很方便合并两个对象的第三方模块。
不难看出 这函数在得出最终的渲染变量对象的时候又再一次 merge了app.locals对象,将开发人员 res.render 传入的对象,res.locals 对象,app.locals 对象三者合并作为最终渲染模板的素材。
知道这个过程之后,很容易就能理解为什么经常在项目入口文件 app.js 中经常看到如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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
上通常挂载变量信息,三者相辅相成的共同构成渲染模板的整个变量信息。
本文为原创文章作为学习交流笔记,如有错误请您评论指教
转载请注明来源:https://isliulei.com/article/当我们调用Express的res-render/