簡體   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