<
>

一文解析Express框架view对象使用

2023-03-11 09:01:48 来源:易采站长站 作者:

目录
Expess View 从指定渲染引擎开始安装依赖从 res.render 函数开始View 的实现mustache 的render 方法的实现一个案例切图案例在 express 中使用 mustachemustache 拆分模板的基本能用法示例

Expess>

以 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 方法:

    View>
    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 扩展方法
      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 的具体实现就交给第三方引擎来实现了。

      mustache>
      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 方法的实现,就不做深入的分析了。

      一个案例切图案例

      需求是这样的,后端使用费>

      使用 exprss 服务 + mustache 模板引擎为基础实现一个简单的切图服务

        Express 创建服务和路由Nodemon 监听文件变化,重新启动路由esno + TypeScript + es Module 编写服务端代码prettier 格式化文件

        在>
        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>
            定义模板文件引用模板文件,以及引入文件下的模板的方法在模板中使用变量条件判断列表渲染

            mustache 官方 Github 仓库,需要研究的可以自己访问学习,更多具体的用法。

            示例

            形成一个约定:因为只做简单的切图工作,view>

              main.server.ts

              读取 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}}} 插入数据根据 html 渲染出数据
                {{#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 等等技术。可以自己尝试一下,如果觉得还方便,可以给一个星星:

                  static-cutouts-express

                  以上就是一文解析Express框架view对象使用的详细内容,更多关于Express框架view对象的资料请关注易采站长站其它相关文章!

暂时禁止评论

微信扫一扫

易采站长站微信账号