无法在嵌套函数中打印正确的内部 HTML 消息



我正在开发一个食谱页面,其中有一系列相互连接的按钮和帖子。按钮上有"派"one_answers"蛋糕"等配方类别的名称。当你点击"派"按钮时,你只会看到分类为"派"的帖子。按钮和帖子都有数据属性,上面有它们的配方类别。

我能够做到这一点,然而,当你点击食谱类别按钮时,我遇到了问题,并且没有相应的帖子。为此,我创建了一个空的"#message"div,如果没有找到菜谱帖子,它将输出一条消息,如果有菜谱帖子,则输出一个空字符串。

当我点击一个有帖子的食谱按钮时,我会收到消息中的"无食谱"文本。同样奇怪的是,它似乎只将正确的消息应用于最后一个按钮/帖子,在本例中是"蛋糕"。

有人能解释一下为什么不起作用吗?我知道这可能是范围/关闭问题,但我不确定发生了什么。

//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";
}
});
}
});

查看过滤器的运行情况。你总是会得到匹配的和不匹配的,所以if和else代码都将始终运行

你想做的是在过滤器中隐藏/显示帖子,显示时返回true,隐藏时返回false

这样,如果没有匹配,则得到的数组长度将为0,如果有匹配的,则为1或更大

然后在确定是否有任何显示以显示/隐藏消息之后再进行另一次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,因为你的按钮保证会有一个显示的

这里有一个让你的想法发挥作用的简单方法
它使用具有事件委派的事件侦听器。

有关进一步的说明,请参阅代码中的注释。

// 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>

最新更新