Pug / Jade

时间:2017-08-22 18:36:45

标签: javascript node.js templates pug pugjs

据我所知,Pug不支持动态包含或扩展模板。即

extend path/to/template 

有效,但不是

extend #{dynamic_path_to_template}

是否有一种解决方法(无论如何复杂)允许在运行时修改视图使用的模板的相同目标

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

4 个答案:

答案 0 :(得分:0)

目前无法实现此目的,但您可以在没有动态扩展的情况下制定应用程序架构。

可能的解决方案#1

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

    layout.jade:
    
    if conditionalVariable
        include firstLayout.jade
    else
        include otherLayout
    
  2. 在您的视图中,展开layout.jade,并在控制器中定义conditionalVariabletrue / false):

    view.jade:
    
    extends layout
    
    block content
        p here goes my content!
    
  3. 可能的解决方案#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. 可能的解决方案#3

      使用类似terraform的东西,它使用pug作为渲染引擎,但它可以让你使用像这样的动态部分

      != partial(dynamicFileFromVariable)
      

答案 1 :(得分:0)

为了进行动态包含,您将必须使用未转义的字符串插值法,在路径中的主.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}

上面的示例特定于我自己的用例,但它应该很容易适应它。

答案 2 :(得分:0)

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

我创建了一个函数,该函数通过给模板提供路径来呈现模板并将其传递给options对象。也许对您的情况也有帮助

for line in dedupped_stream(...):
    ...

,然后按照模板中的说明使用它:

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

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

答案 3 :(得分:0)

有效!

首先,设置 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()
}

server/index.js

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

file.pug

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