我试图动态渲染部分(意思是,在程序运行之前,部分名称是未知的)。我发现使用Handlebars docs中的简单lookup
子表达式可以实现这一点。
动态部分
可以动态选择要执行的部分 使用子表达式语法。
{{> (whichPartial) }}
将评估
whichPartial
,然后呈现其名称返回的部分 这个功能。Subexpressions不解析变量,因此
whichPartial
必须是一个功能。如果一个简单变量具有部分名称,那么它就是 可以通过查找帮助程序解决它。
{{> (lookup . 'myVariable') }}
这是我的设置:
我的页面包含以下调用:
{{> components/common/panel content="components/common/category-images"}}
然后,在components/common/panel.html
,我有:
<div class="panel">
{{> (lookup . 'content')}}
</div>
当这个运行时,我收到一个错误:
Debug: internal, implementation, error
Error: Uncaught error: The partial components/common/category-images could not be found
如果我直接用以下方式调用部分:
{{> components/common/category-images}}
它工作正常,所以我知道该文件存在。更奇怪的是,如果我包含原始行,然后直接调用部分注释掉,它就可以工作:
{{> components/common/panel content="components/common/category-images"}}
{{!-- {{> components/common/category-images}} --}}
但是,只要删除该注释行,我就会再次收到错误,即找不到该部分。我很困惑。有人可以帮忙吗?
更新
我找到了以下似乎相关的文件:stencil-cli/lib/templateAssembler.js
。以下是内容:
var _ = require('lodash'),
Async = require('async'),
Fs = require('fs'),
Path = require('path'),
internals = {
options: {
templatesFolder: Path.join(process.cwd(), 'templates'),
extension: '.html',
partialRegex: /\{\{>\s*([_|\-|a-zA-Z0-9\/]+)[^{]*?}}/g,
dynamicComponentRegex: /\{\{\s*?dynamicComponent\s*(?:'|")([_|\-|a-zA-Z0-9\/]+)(?:'|").*?}}/g
}
};
module.exports.assemble = assemble;
module.exports.getTemplateContentSync = getTemplateContentSync;
/**
* Parses the passed in templates and resolves all of their partials.
*
* @param templates
* @param callback
*/
function assemble(templates, callback) {
getTemplatePaths(templates, function(err, templatePaths) {
if (err) {
return callback(err);
}
getContent(templatePaths, callback);
});
}
function getTemplateContentSync(templateFile) {
var path = Path.join(internals.options.templatesFolder, templateFile + internals.options.extension);
return Fs.readFileSync(path).toString();
}
/**
* Parses the passed in templates and returns all of the partials for each one
*
* @param templates
* @param callback
*/
function getTemplatePaths(templates, callback) {
var templatePaths = [],
missingTemplates = [];
if (templates === undefined) {
return callback(null);
}
if (! _.isArray(templates)) {
templates = [templates];
}
Async.each(templates, resolvePartials, function (err) {
if (err) {
return callback(err);
}
if (missingTemplates.length > 0) {
return callback(new Error(
'The following template(s) are/is missing: \n' + missingTemplates.join('\n')
));
}
callback(null, templatePaths);
});
function resolvePartials(templateFile, callback) {
var file = Path.join(internals.options.templatesFolder, templateFile + internals.options.extension);
console.log(file);
Fs.readFile(file, {encoding: 'utf-8'}, function(err, content) {
var componentPaths = [],
matches = [],
match,
partialPath;
if (err) {
missingTemplates.push(templateFile);
return callback();
}
templatePaths.push(templateFile);
match = internals.options.partialRegex.exec(content);
while (match !== null) {
partialPath = match[1];
if (templatePaths.indexOf(partialPath) === -1) {
matches.push(partialPath);
}
match = internals.options.partialRegex.exec(content);
}
match = internals.options.dynamicComponentRegex.exec(content);
while (match !== null) {
if (componentPaths.indexOf(match[1]) === -1) {
componentPaths.push(match[1]);
}
match = internals.options.dynamicComponentRegex.exec(content);
}
Async.each(componentPaths, function(componentPath, callback) {
Fs.readdir(Path.join(internals.options.templatesFolder, componentPath), function(err, files) {
if (err) {
return callback(err);
}
matches = _.reduce(files, function(acc, file) {
// remove the extension
partialPath = Path.join(componentPath, Path.parse(file).name);
if (templatePaths.indexOf(partialPath) === -1) {
acc.push(partialPath);
}
return acc;
}, matches);
callback();
});
}, function(err) {
if (err) {
return callback(err);
}
Async.each(matches, resolvePartials, callback);
});
});
}
}
/**
* Takes a list of templates and grabs their content. It returns simple key/val pair
* of filename => content
*
* @param templatePaths
* @param callback
*/
function getContent(templatePaths, callback) {
Async.reduce(templatePaths, {}, getContentReducer, callback);
function getContentReducer(acc, templatePath, reduceCallback) {
var file = Path.join(internals.options.templatesFolder, templatePath + internals.options.extension);
Fs.readFile(file, {encoding: 'utf-8'}, function(err, content) {
if (err) {
return reduceCallback(err);
}
acc[templatePath] = content;
reduceCallback(null, acc);
});
}
}
对每个模板文件/部分文件递归调用此函数,我可以通过我的console.log
语句确认category-images
部分不在我的非工作版本的文件列表中码。看起来服务器未设置为从子表达式语法解析模板。此行显示用于查找partials的正则表达式:
partialRegex: /\{\{>\s*([_|\-|a-zA-Z0-9\/]+)[^{]*?}}/g
我假设在评估子表达式之前运行,因此部分永远不会被识别。这听起来像是问题吗?是否存在子表达式部分未被评估的原因?