繁体   English   中英

Pug/Jade 中动态包含的解决方法

[英]Workaround to dynamic includes in Pug/Jade

我了解 Pug 不支持模板中的动态包含或扩展。 IE

extend path/to/template 

有效但无效

extend #{dynamic_path_to_template}

是否有一种解决方法(无论多么复杂),可以实现在运行时修改视图使用的模板的相同目标

上下文:我的用例是我正在开发一个 npm 模块,并且用于扩展其他视图的模板位于模块内部。 发布并安装模块后,将定义路径(即 node_modules/my_module/path/to/template),但在开发阶段,我只需要能够“npm link”到模块并拥有模板工作。 我也不想对链接进行硬编码,这样我就可以发布与测试相同的代码。

目前还没有办法做到这一点,但是您可以在没有动态扩展的情况下制定您的应用程序架构。

可能的解决方案#1

  1. 制作一个 layout.jade 有条件地包含多个布局:

     layout.jade: if conditionalVariable include firstLayout.jade else include otherLayout
  2. 在您看来,扩展layout.jade并在控制器中定义conditionalVariable ( true / false ):

     view.jade: extends layout block content p here goes my content!

可能的解决方案#2

  1. 将配置传递给布局

    - var lang = req.getLocale(); doctype html block modifyLayout
  2. 将项目拆分为多个入口,每个入口扩展布局并传递其不同的配置,并在不同的块中包含不同的东西

    extends ../layout block modifyLayout - var lang = "en" //force language to be en in this page. block body include my-page-body

可能的解决方案#3

使用类似terraform的东西,它使用 pug 作为其渲染引擎,但它使您能够使用这样的动态部分

!= partial(dynamicFileFromVariable)

我也遇到了这个问题,在寻找解决方案时发现了这个问题。 我的解决方案类似于 Nikolay Schambergs Answer,但我认为我应该分享它。

我创建了一个函数,它通过给它一个路径来呈现模板并将它传递给选项对象。 也许它对你的情况也有帮助

const includeFunc = (pathToPug, options = {}) => {
    return pug.renderFile(pathToPug, options); //render the pug file
}

const html = pug.renderFile('template.pug', {include: includeFunc});

然后在您的模板中使用它:

body
  h1 Hello World
  |!{include(dynamicPugFilePathFromVariable)}

有用!

首先,设置 res.locals 中间件。

中间件/setResLocals.js

const pug = require('pug')
const path = require('path')
module.exports = function(req, res, next) {
  res.locals.include = (pathToPug, options = {}) => { // used for imitate includ pug function
    return pug.renderFile(pathToPug, options); //render the pug file
  }
  res.locals.__PATH__ = path.join(__dirname, '../')
  next()
}

服务器/index.js

app.use(require('../middlewares/setResLocals'))

文件.pug

|!{include(`${__PATH__}/${something}`)}

为了进行动态包含,您将不得不使用未转义字符串插值,将在您的主 .pug 文件之前预编译的 pug 内容插入到您的路线中。 换句话说,它的工作原理如下:

1) 一些 .pug 文件被预编译成 HTML 2) HTML 被送入另一个 .pug 文件编译过程

这是一个如何做的例子

在您的路由器文件中(routes.js 或其他)

var pug = require('pug')
var html = []
var files = ['file1','file2'] // file names in your views folders
let dir = path.resolve(path.dirname(require.main.filename) + `/app/server/views/`)
//dir is the folder with your templates
app.get('/some-route', (req,res) => {
    for (let n = 0; n < files.length; n++) {

        let file = path.resolve(dir + '/' + files[n] + `.pug`)
        fs.access(file, fs.constants.F_OK, (err) => {
            if (!err) {
                html.push(pug.renderFile(file, data))
                if (n === files.length - 1) {
                    res.render('dashboard', {html})
                }
            }
            else {
                res.status(500).json({code:500,status:"error", error:"system-error"})
            }
        })
    }
})

在您想要的 .pug 文件中:

for item in html
    .
        !{item}

上面的例子是针对我自己的用例的,但它应该很容易适应它。

我知道,现在回答有点晚了。 但是我通过 pug 文档中的一些信息发现了一种适合我的目的的可能性:

如果路径是绝对路径(例如, include /root.pug ),则通过添加options.basedir来解决。 否则,将相对于正在编译的当前文件解析路径。

因此,我通过相对路径提供了我的大部分 pug 模块,并且我想要动态交换的东西被组织在同名但在不同文件夹(想想主题)的 pug 文件中,并通过绝对路径包含它们。 然后我更改basedir选项以动态选择一组 pug 文件(如选择主题)。

愿这对其他人也有帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM