我写了一个非常基本的网络应用程序,它从API中提取食谱数据。通过推送到javascript文件中定义的html模板来呈现数据。布局通过CSS中的浮动网格进行控制。
呈现结果并推送到模板的代码部分:
function displayRecipeSearchData(data) {
var results = ' ';
if (data.hits.length) {
data.hits.forEach(function(item) {
results += template.item(item);
});
}
else {
results += '<p> No results </p>';
}
$('#js-search-results').html(results);
}
显示响应的html模板:
const template = {
item: function(item) {
return '<div class ="col-4">' +
'<div class ="result">' +
'<div class="recipelabel">' +
'<div class="reclist">' + item.recipe.ingredientLines + '</div><!-- end reclist -->' +
'<p class="label">' + item.recipe.label + '</p>' +
'<div class="thumbnail">' +
'<a href="'+ httpsTransform(item.recipe.url) + '" target="_blank">' +
'<img src="' + item.recipe.image + '"alt="' + item.recipe.label + '">' +
'</a>' +
'<div class="recipesource">' +
'<p class="source">' + item.recipe.source + '</p>' +
'</div><!-- end recipesource -->' +
'</div><!-- end thumbnail -->' +
'</div><!-- end recipelabel -->' +
'</div><!-- end result -->' +
'</div><!-- end col-4 -->';
}
};
我正在尝试更改displayRecipeSearchData函数中的逻辑,这样,对于每组三个结果,<div></div>
围绕三个结果的块。这样行/列始终在flex网格中工作。我已经尝试了几种方法,但还没有得到正确的语法/逻辑。嵌套在现有语句中的if语句是否有效?
if(i % 3 === 0 ){ results. += '<div class="row">''</div>'}
任何建议都将不胜感激。
答案 0 :(得分:1)
您可以使用另一个变量来存储一行HTML:
function displayRecipeSearchData(data) {
var results = ' ', row = '';
if (data.hits.length) {
data.hits.forEach(function(item, i) {
row += template.item(item);
if (i % 3 == 2) { // wrap row and add to result
results += '<div class="row">' + row + '</div>';
row = '';
}
});
if (row.length) { // flush remainder into a row
results += '<div class="row">' + row + '</div>';
}
}
else {
results += '<p> No results </p>';
}
$('#js-search-results').html(results);
}
答案 1 :(得分:0)
在我看来,你肯定是这么做的。
而不是手动将模板写为字符串并尝试将字符串注入正确的位置(可能创建无效的html),您应该使用javascripts内置元素创建。在自己的职能中创造孩子也会更加模块化。使用函数而不是对象来保存对象创建者也会容易得多。我的版本可能有更多代码,但从长远来看,修改起来会容易得多
const Itemizer = function(){
this.items = [];
const createEl = function(elType, classes, attributes, text, html){
let el = document.createElement(elType)
for(let i = 0; i < classes.length; i++){
el.classList.add(classes[i]
}
for(let attr in attributes){
el.setAttribute(attr, attributes[attr])
}
if(text){
el.innerText = text
}
if(html){
el.innerHTML = html
}
return el
};
const createThumbnail = function(url, image, alt, source){
let thumbnail = createEl("DIV", ["thumbnail"]),
link = createEl("A", [], {href: httpsTransform(url)}),
img = createEl("IMG", [], {src: image, alt: label});
rSource = createRecipeSource(source)
link.appendChild(img);
thumbnail.appendChild(link);
thumbnail.appendChild(rSource)
return thumbnail
};
const createRecipeSource = function(source){
let wrapper = createEl("DIV", ["recipe-source"]);
wrapper.appendChild(createEl("P", ["source"], {}, source))
return wrapper
}
const createRecipeLabel = function({
recipe: {
ingredientLines,
label,
url,
source
}
}){
let labelWrapper = createEl("DIV", ["recipe-label"),
ingredients = createEl("DIV", ["rec-list"], {}, false, ingredientLines),
recipeLabel = createEl("P", ["label"], {}, label),
thumbnail = createThumbnail(url, image, label, source)
labelWrapper.appendChild(ingredients)
labelWrapper.appendChild(recipeLabel)
labelWrapper.appendChild(thumbnail)
return labelWrapper
}
const createNewItem = function(data){
let columnWrapper = createEl("DIV", ["col-4"]),
result = createEl("DIV", ["result"]),
label = createRecipeLabel(data)
columnWrapper.appendChild(result)
result.appendChild(label)
this.items.push(columnWrapper)
return columnWrapper
}.bind(this)
const getItems = function(){
return this.items
}.bind(this)
const getRows = function(){
const rows = []
let row;
for(let i = 0; i < this.items.length; i++){
const item = this.items[i]
if(i % 3 === 0){
row = createEl("DIV", ["row"])
rows.push(row)
}
row.appendChild(item)
}
return rows;
}.bind(this)
return {
add: createNewItem,
get: getItems,
rows: getRows
}
}
然后您可以使用如下函数:
const template = new Itemizer()
function displayRecipeSearchData(data) {
let rows
if (data.hits.length) {
for(let i = 0; i < data.hits.length; i++){
template.add(data.hits[i])
}
rows = template.rows()
} else {
const p = document.createElement("P")
p.innerText = "No Results")
rows = [p]
}
const resultsWrapper = document.getElementById("js-search-results");
for(let i = 0; i < rows.length; i++){
resultsWrapper.appendChild(rows[i])
}
}
将css类与连字符分开也是一种很好的形式,所以我替换了一些你的类名来反映
同样重要的是要注意,实际上您不需要超过1行。如果您将所有项目包装在一个row
部分中,当列数达到网格限制时,列会自动溢出到下一行
我的最后一点是永远不会使用目标空白。它违背了正确的用户体验,并在您的应用程序中创建安全漏洞。如果您的用户需要在新标签页中打开,则可以按住ctrl
或点击“在新标签页中打开”