Использование интерполяции внутри Node.js EJS включает
Приложение My Express использует EJS, а мой каталог представлений выглядит следующим образом:
./views
./contents
home.ejs
./includes
header.ejs
footer.ejs
layout.ejs
Я пытаюсь загрузить home.ejs в свой layout.ejs, условно основанный на локальной переменной с именем contents
в моих маршрутах /index.js. Этот файл выглядит следующим образом:
/*
* GET home page.
*/
exports.index = function(req, res){
res.render('index', { title: 'Home', contents: 'home.ejs' });
};
В идеале я мог просто написать (в layout.ejs):
<% include '/contents' + contents %>
где конечное "содержимое" - это локальная переменная, которая содержит относительный путь к тексту тела, который требуется загрузить.
Но, увы, похоже, EJS всегда интерпретирует текст, следуя директиве include
буквально, и нет никакой возможности для какой-либо магии интерполяции.
Я также пытался безрезультатно:
<% function yieldContent(contents){ %>
<% var contentPath = 'contents/' + contents; %>
<% include contentPath %>
<% }; %>
<% loadContent(); %>
Есть ли у кого-нибудь креативное решение для условного включения представления на основе переменной, передаваемой по маршрутам?
Ответы
Ответ 1
Я думаю, что в EJS такой способ не существует. Это может нарушить разделение бизнес-логики и взгляда.
Решение может состоять в том, чтобы сделать подтеку в контроллере и передать его содержимое в макет.
Для рендеринга подматрицы в контроллере используйте что-то вроде этого:
var ejs = require('ejs'),
, fs = require('fs')
, home = ejs.render(fs.readFileSync("contents/home.ejs", "utf-8"))
Ответ 2
В версии 2 EJS функция include
делает это хорошо. С его помощью включенные вставляются во время выполнения, поэтому переменные могут использоваться как пути.
В этом случае решение может быть:
<%- include('contents/' + contents) %>
При необходимости функция может иметь и другой аргумент:
<%- include('mypathname', {foo:"bar"}) %>
Имя пути должно относиться к шаблону, который вызывает функцию.
Ответ 3
В настоящее время это не реализовано в ejs, но есть этот запрос на обсуждение и pull, который предлагает функциональность.
https://github.com/visionmedia/ejs/issues/93
Ответ 4
в вашей функции рендеринга вы можете включить fs.readFileSync
и __dirname
.
Отобразить страницу с такими параметрами
res.render('pages/'+req.file,{file_get_contents:fs.readFileSync,__dirname:__dirname});
Затем вы можете использовать его на странице .ejs
следующим образом. Это остается на стороне сервера.
<% var products=JSON.parse(file_get_contents(__dirname+'/web/data/products.json','utf8')) %>
Вы можете распечатать данные на клиентском HTML, как это.
<%- JSON.stringify(products)%>
Примечание. Использование этого метода означает, что у вас есть fs
, который находится где-то в верхней части вашего script.
var fs = require('fs')