<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
以 mustache 渲染引擎為例,需要初始化一些程式碼
const app = express() app.set("view engine", "mustache"); app.engine("mustache", mustacheExpress()); app.set("views", toAbsolutePath("./views"));
pnpm install mustache mustache-express
render 函數接收兩個引數,第一個 view 的路徑,第二個渲染資料。
res.render = function render(view, options, callback) { // 呼叫 app.render app.render(view, opts, done); };
下面是 app.render 程式碼實現
app.render = function render(name, options, callback) { // view 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); } // prime the cache if (renderOptions.cache) { cache[name] = view; } } // render tryRender(view, renderOptions, done); };
在 view 不在的情況下,會用 View 範例化 view, 最後呼叫 tryRender 函數,tryRender 函數會呼叫 view.render 方法:
module.exports = View; function View(name, options) { // store loaded engine this.engine = opts.engines[this.ext]; // lookup path this.path = this.lookup(fileName); }
跟一般的建構函式一樣,初始化一些屬性,用傳入的 opts 合併一些屬性。
View.prototype.lookup = function lookup(name) {} View.prototype.render = function render(options, callback) { this.engine(this.path, options, callback); } View.prototype.resolve = function resolve(dir, file) {}
render 的具體實現就交給第三方引擎來實現了。
Writer.prototype.render = function render (template, view, partials, config) { var tags = this.getConfigTags(config); var tokens = this.parse(template, tags); var context = (view instanceof Context) ? view : new Context(view, undefined); return this.renderTokens(tokens, context, partials, template, config); };
render 函數呼叫 renderTokens 方法來解析,具體 renderTokens 方法的實現,就不做深入的分析了。
需求是這樣的,後端使用費 Node.js 開發,沒有 JS 執行時,為了能夠快速的完成專案,頁面的切頭由前端完成。此時頁面多,任務重,React/Vue 這種現代框架,需要伺服器端渲染,後端不想用 Node.js,增加複雜度。因為前端 Node.js 能夠使用模板渲染,並且模板種類很多,模板能夠解決複用的問題,所以前端功能化能夠解決,現代前端能結局的問題。
使用 exprss 服務 + mustache 模板引擎為基礎實現一個簡單的切圖服務
import express from "express"; import mustacheExpress from "mustache-express"; app.engine("mustache", mustacheExpress()); app.set("view engine", "mustache"); app.set("views", toAbsolutePath("./views")); // 指定檢視路徑
app.get(url, async (_, res) => { res.render(url, data); });
mustache 官方 Github 倉庫,需要研究的可以自己存取學習,更多具體的用法。
形成一個約定:因為只做簡單的切圖工作,view + data 檔案使用 render 函數渲染的時候一一對應,這樣就減少了很多的樣板程式碼。 ·
讀取 views/
資料夾下的所有檢視檔案,佈局檔案不包含(簡化),將 /static
目錄設定為靜態資料夾目錄。路由不在單獨的寫了,此處統一處理為與檢視相同命名用於簡單的渲染。
// express import express from "express"; import mustacheExpress from "mustache-express"; // config import cutConfig from "./cut.config"; import defineVars from "iesmo"; // node import { resolve } from "path"; import fs from "node:fs"; const { __dirname } = defineVars(import.meta); export const toAbsolutePath = (p) => resolve(__dirname, p); const routes = fs .readdirSync(toAbsolutePath("./views/")) .map((file) => { if (!/.mustache$/.test(file)) return null; return file.replace(/.mustache$/, "").toLowerCase(); }) .filter((i) => i !== null); const app = express(); app.engine("mustache", mustacheExpress()); app.set("view engine", "mustache"); app.set("views", toAbsolutePath("./views")); app.use("/static", express.static("static")); routes.forEach((route) => { let url = route === "index" ? "/" : `/${route}`; app.get(url, async (_, res) => { let data = (await import(`./data/${route}.ts`)).default; res.render(route as string, data); }); }); app.listen(cutConfig.port, () => { console.log("server listening on port: ", cutConfig.port); });
以 index.mustache 模板為範例:
資料存在 /data
資料夾下,預設輸出一個 JS 物件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>{{{title}}}</title> {{#links}} <link href="{{{href}}}" rel="external nofollow" rel="external nofollow" rel="stylesheet" /> {{/links}} {{#scriptsHead}} <script src="{{{src}}}"></script> {{/scriptsHead}} </head> <body> {{>tpls/list }} {{>layout/footer}} {{#scriptBody}} <script src="{{{src}}}"></script> {{/scriptBody}} </body> </html>
{{{title}}}
插入資料{{#links}} <link href="{{{href}}}" rel="external nofollow" rel="external nofollow" rel="stylesheet" /> {{/links}}
<body> {{>tpls/list }} {{>layout/footer}} </body>
以上行為表示 tpls 目錄下的 list 模板檔案和 layout 目錄下的 footer 模板檔案
下面是一個具體的例子,使用到了 jQuery, Bootstrap 等等技術。可以自己嘗試一下,如果覺得還方便,可以給一個星星:
以上就是一文解析Express框架view物件使用的詳細內容,更多關於Express框架view物件的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45