无法在嵌套函数中打印正确的 innerHTML 消息
Can't print correct innerHTML message within a nested function
我正在制作一个食谱页面,其中有一系列相互关联的按钮和帖子。这些按钮具有食谱类别的名称,例如馅饼和蛋糕。当您点击 'Pie' 按钮时,您只会看到分类为 'Pie' 的帖子。按钮和帖子都有数据属性,那里有它们的食谱类别。
我能够让它工作,但是,当您单击食谱类别按钮时我遇到了问题,并且没有相应的帖子。为此,我创建了一个空的“#message”div,如果没有找到菜谱帖子,它会输出一条消息,如果有菜谱帖子,它会输出一个空字符串。
当我单击包含帖子的食谱按钮时,我在消息中收到了 'No Recipes' 文本。同样奇怪的是,它看起来只对最后一个 button/post 应用了正确的消息,在这个例子中是 'Cake'.
有人可以解释为什么这不起作用吗?我知道这可能是一个 scope/closure 问题,但我不确定发生了什么。
//BUTTONS
<section>
<button class="recipe_button" data-btncategory="Pie">
Pie
</button>
<button class="recipe_button" data-btncategory="Cake">
Cake
</button>
</section>
//POSTS
<div id="message"></div>
<section class="recipe" data-postcategory="Pie">
<h2>Pie Recipe</h2>
</section>
<section class="recipe" data-postcategory="Cake">
<h2>Cake Recipe</h2>
</section>
let posts = document.querySelectorAll(".recipe");
let postsArr = Array.from(posts);
let btn = document.querySelectorAll(".recipe_button");
let btnArray = Array.from(btn);
let message = document.getElementById("message");
btnArray.forEach((button) => {
button.onclick = (el) => {
let match = el.target.dataset.btncategory;
postsArr.filter(function(post, i) {
if (post.dataset.postcategory == match) {
posts[i].style.display = "grid";
<-- message not working properly -->
message.innerHTML = "";
} else {
posts[i].style.display = "none";
<-- message not working properly -->
message.innerHTML = "Sorry No Recipes Available";
}
});
}
});
看看您的过滤器 运行ning 怎么样。你总会得到匹配的和不匹配的 - 所以 if 和 else 代码总是 运行
你要做的是 hide/display 过滤器中的帖子,显示时返回 true,隐藏时返回 false
这样的话,如果没有匹配,得到的数组长度将为0,如果有匹配,则为1或更多
然后 if/else 在确定是否有任何内容显示给 show/hide 消息后 if/else
let posts = document.querySelectorAll(".recipe");
let postsArr = Array.from(posts);
let btn = document.querySelectorAll(".recipe_button");
let btnArray = Array.from(btn);
let message = document.getElementById("message");
btnArray.forEach((button) => {
button.onclick = (el) => {
let match = el.target.dataset.btncategory;
let found = postsArr.filter(function(post) {
if (post.dataset.postcategory == match) {
post.style.display = "grid";
return true;
} else {
post.style.display = "none";
return false;
}
}).length;
message.innerHTML = found ? "" : "Sorry No Recipes Available";
}
});
<section>
<button class="recipe_button" data-btncategory="Pie">
Pie
</button>
<button class="recipe_button" data-btncategory="Cake">
Cake
</button>
</section>
//POSTS
<div id="message"></div>
<section class="recipe" data-postcategory="Pie">
<h2>Pie Recipe</h2>
</section>
<section class="recipe" data-postcategory="Cake">
<h2>Cake Recipe</h2>
</section>
话虽如此,该消息永远不会显示 Sorry No Recipes Available
因为您的按钮保证会显示一个
这里有一个让您的想法付诸实践的简单方法。
它使用带有 event delegation.
的事件侦听器
请参阅 in-code 评论以获得进一步说明。
// Identifies DOM elements
const
btnsDiv = document.getElementById("btns"),
posts = [...document.getElementsByClassName("recipe")],
message = document.getElementById("message");
// Calls `filterPosts` when btnsDiv is clicked
btnsDiv.addEventListener("click", filterPosts);
// Defines `filterPosts`
function filterPosts(event){
// Ignores irrelevant clicks
if(!event.target.classList.contains("btn")){ return; }
// Shows message while there is no match
let match = false;
message.classList.remove("hidden");
// Remembers category
const category = event.target.dataset.category;
// Iterates through recipes
posts.forEach( (post) => {
// Hides recipe until it matches
post.classList.add("hidden");
// If recipe matches, shows it and notes the match
if(post.dataset.category == category) {
post.classList.remove("hidden");
match = true;
}
});
// If any match occurred, hides message
if(match == true){
message.classList.add("hidden");
}
}
.hidden{ display: none; }
<div id = "btns">
<button class="btn" data-category="Pie">Pie </button>
<button class="btn" data-category="Cake"> Cake </button>
<button class="btn" data-category="Pasta"> Pasta </button>
</div>
<div id="message" class="hidden">Sorry No Recipes Available</div>
<div class="recipe hidden" data-category="Pie">
<h2>Pie Recipe 1</h2>
</div>
<div class="recipe hidden" data-category="Cake">
<h2>Cake Recipe 1</h2>
</div>
<div class="recipe hidden" data-category="Cake">
<h2>Cake Recipe 2</h2>
</div>
我正在制作一个食谱页面,其中有一系列相互关联的按钮和帖子。这些按钮具有食谱类别的名称,例如馅饼和蛋糕。当您点击 'Pie' 按钮时,您只会看到分类为 'Pie' 的帖子。按钮和帖子都有数据属性,那里有它们的食谱类别。
我能够让它工作,但是,当您单击食谱类别按钮时我遇到了问题,并且没有相应的帖子。为此,我创建了一个空的“#message”div,如果没有找到菜谱帖子,它会输出一条消息,如果有菜谱帖子,它会输出一个空字符串。
当我单击包含帖子的食谱按钮时,我在消息中收到了 'No Recipes' 文本。同样奇怪的是,它看起来只对最后一个 button/post 应用了正确的消息,在这个例子中是 'Cake'.
有人可以解释为什么这不起作用吗?我知道这可能是一个 scope/closure 问题,但我不确定发生了什么。
//BUTTONS
<section>
<button class="recipe_button" data-btncategory="Pie">
Pie
</button>
<button class="recipe_button" data-btncategory="Cake">
Cake
</button>
</section>
//POSTS
<div id="message"></div>
<section class="recipe" data-postcategory="Pie">
<h2>Pie Recipe</h2>
</section>
<section class="recipe" data-postcategory="Cake">
<h2>Cake Recipe</h2>
</section>
let posts = document.querySelectorAll(".recipe");
let postsArr = Array.from(posts);
let btn = document.querySelectorAll(".recipe_button");
let btnArray = Array.from(btn);
let message = document.getElementById("message");
btnArray.forEach((button) => {
button.onclick = (el) => {
let match = el.target.dataset.btncategory;
postsArr.filter(function(post, i) {
if (post.dataset.postcategory == match) {
posts[i].style.display = "grid";
<-- message not working properly -->
message.innerHTML = "";
} else {
posts[i].style.display = "none";
<-- message not working properly -->
message.innerHTML = "Sorry No Recipes Available";
}
});
}
});
看看您的过滤器 运行ning 怎么样。你总会得到匹配的和不匹配的 - 所以 if 和 else 代码总是 运行
你要做的是 hide/display 过滤器中的帖子,显示时返回 true,隐藏时返回 false
这样的话,如果没有匹配,得到的数组长度将为0,如果有匹配,则为1或更多
然后 if/else 在确定是否有任何内容显示给 show/hide 消息后 if/else
let posts = document.querySelectorAll(".recipe");
let postsArr = Array.from(posts);
let btn = document.querySelectorAll(".recipe_button");
let btnArray = Array.from(btn);
let message = document.getElementById("message");
btnArray.forEach((button) => {
button.onclick = (el) => {
let match = el.target.dataset.btncategory;
let found = postsArr.filter(function(post) {
if (post.dataset.postcategory == match) {
post.style.display = "grid";
return true;
} else {
post.style.display = "none";
return false;
}
}).length;
message.innerHTML = found ? "" : "Sorry No Recipes Available";
}
});
<section>
<button class="recipe_button" data-btncategory="Pie">
Pie
</button>
<button class="recipe_button" data-btncategory="Cake">
Cake
</button>
</section>
//POSTS
<div id="message"></div>
<section class="recipe" data-postcategory="Pie">
<h2>Pie Recipe</h2>
</section>
<section class="recipe" data-postcategory="Cake">
<h2>Cake Recipe</h2>
</section>
话虽如此,该消息永远不会显示 Sorry No Recipes Available
因为您的按钮保证会显示一个
这里有一个让您的想法付诸实践的简单方法。
它使用带有 event delegation.
请参阅 in-code 评论以获得进一步说明。
// Identifies DOM elements
const
btnsDiv = document.getElementById("btns"),
posts = [...document.getElementsByClassName("recipe")],
message = document.getElementById("message");
// Calls `filterPosts` when btnsDiv is clicked
btnsDiv.addEventListener("click", filterPosts);
// Defines `filterPosts`
function filterPosts(event){
// Ignores irrelevant clicks
if(!event.target.classList.contains("btn")){ return; }
// Shows message while there is no match
let match = false;
message.classList.remove("hidden");
// Remembers category
const category = event.target.dataset.category;
// Iterates through recipes
posts.forEach( (post) => {
// Hides recipe until it matches
post.classList.add("hidden");
// If recipe matches, shows it and notes the match
if(post.dataset.category == category) {
post.classList.remove("hidden");
match = true;
}
});
// If any match occurred, hides message
if(match == true){
message.classList.add("hidden");
}
}
.hidden{ display: none; }
<div id = "btns">
<button class="btn" data-category="Pie">Pie </button>
<button class="btn" data-category="Cake"> Cake </button>
<button class="btn" data-category="Pasta"> Pasta </button>
</div>
<div id="message" class="hidden">Sorry No Recipes Available</div>
<div class="recipe hidden" data-category="Pie">
<h2>Pie Recipe 1</h2>
</div>
<div class="recipe hidden" data-category="Cake">
<h2>Cake Recipe 1</h2>
</div>
<div class="recipe hidden" data-category="Cake">
<h2>Cake Recipe 2</h2>
</div>