无法在嵌套函数中打印正确的 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>