简体   繁体   English

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

[英]Workaround to dynamic includes in Pug/Jade

I understand that Pug does not support dynamic includes or extends in templates.我了解 Pug 不支持模板中的动态包含或扩展。 Ie IE

extend path/to/template 

works but not有效但无效

extend #{dynamic_path_to_template}

Is there a workaround (however convoluted) that will allow the same goal of modifying the template used by a view at runtime是否有一种解决方法(无论多么复杂),可以实现在运行时修改视图使用的模板的相同目标

Context : My use case is that I am developing an npm module and the template being used to extend other views is located inside the module.上下文:我的用例是我正在开发一个 npm 模块,并且用于扩展其他视图的模板位于模块内部。 After the module is published and installed, the path will be defined (ie. node_modules/my_module/path/to/template) but during the development phase, I need to just be able to "npm link" to the module and have the templates work.发布并安装模块后,将定义路径(即 node_modules/my_module/path/to/template),但在开发阶段,我只需要能够“npm link”到模块并拥有模板工作。 I also would prefer not to hard code the links so I can publish the same code as tested.我也不想对链接进行硬编码,这样我就可以发布与测试相同的代码。

There is no way to do this for now, but you can work out your application architecture without dynamic extends.目前还没有办法做到这一点,但是您可以在没有动态扩展的情况下制定您的应用程序架构。

Possible solution #1可能的解决方案#1

  1. Make a layout.jade that conditionally include multiple layouts:制作一个 layout.jade 有条件地包含多个布局:

     layout.jade: if conditionalVariable include firstLayout.jade else include otherLayout
  2. In your view, extend layout.jade , and define conditionalVariable in the controller ( true / false ):在您看来,扩展layout.jade并在控制器中定义conditionalVariable ( true / false ):

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

Possible solution #2可能的解决方案#2

  1. Pass configurations to the layout将配置传递给布局

    - var lang = req.getLocale(); doctype html block modifyLayout
  2. split the project into multiple entrances, each entrance extends the layout and passes its different configs, and includes different things in different blocks将项目拆分为多个入口,每个入口扩展布局并传递其不同的配置,并在不同的块中包含不同的东西

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

Possible solution #3可能的解决方案#3

use something like terraform which uses pug as its rendering engine, but it enables you to use dynamic partials like this使用类似terraform的东西,它使用 pug 作为其渲染引擎,但它使您能够使用这样的动态部分

!= partial(dynamicFileFromVariable)

I had this issue aswell and found this question while searching for a solution.我也遇到了这个问题,在寻找解决方案时发现了这个问题。 My solution is similar to Nikolay Schambergs Answer, but i thought i should share it.我的解决方案类似于 Nikolay Schambergs Answer,但我认为我应该分享它。

I've created a function that renders templates by giving it a path and passed it to the options object.我创建了一个函数,它通过给它一个路径来呈现模板并将它传递给选项对象。 Maybe it helps in your case aswell也许它对你的情况也有帮助

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

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

and then use it as followed in your template:然后在您的模板中使用它:

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

It works!有用!

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

middlewares/setResLocals.js中间件/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服务器/index.js

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

file.pug文件.pug

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

In order to do dynamic include, you will have to use Unescaped String Interpolation, inserting pug contents that are pre-compiled before your main .pug file inside your route.为了进行动态包含,您将不得不使用未转义字符串插值,将在您的主 .pug 文件之前预编译的 pug 内容插入到您的路线中。 In other words it works as follows:换句话说,它的工作原理如下:

1) Some .pug files are pre-compiled into HTML 2) The HTML gets fed into another .pug file compilation process 1) 一些 .pug 文件被预编译成 HTML 2) HTML 被送入另一个 .pug 文件编译过程

Here's an example how to do it这是一个如何做的例子

Inside your router file (routes.js or whatever)在您的路由器文件中(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"})
            }
        })
    }
})

Inside your desired .pug file:在您想要的 .pug 文件中:

for item in html
    .
        !{item}

The example above is specific to my own use case, but it should be easy enough to adapt it.上面的例子是针对我自己的用例的,但它应该很容易适应它。

I know, this is a bit late for answering.我知道,现在回答有点晚了。 But I found a possibility suitable for my purpose by this bit of information from the pug docs:但是我通过 pug 文档中的一些信息发现了一种适合我的目的的可能性:

If the path is absolute (eg, include /root.pug ), it is resolved by prepending options.basedir .如果路径是绝对路径(例如, include /root.pug ),则通过添加options.basedir来解决。 Otherwise, paths are resolved relative to the current file being compiled.否则,将相对于正在编译的当前文件解析路径。

So, I provide most of my pug modules by relative paths and the stuff I want to exchange dynamically is organised in pug files of the same name but in different folders (think theme) and include them by absolute paths .因此,我通过相对路径提供了我的大部分 pug 模块,并且我想要动态交换的东西被组织在同名但在不同文件夹(想想主题)的 pug 文件中,并通过绝对路径包含它们。 Then I change the basedir option to dynamically choose a set of pug files (like choosing the theme).然后我更改basedir选项以动态选择一组 pug 文件(如选择主题)。

May this help others, too.愿这对其他人也有帮助。

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

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