You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于JavaScript搜索结果隐藏指定div的实现问题求助

问题解决:搜索栏模式切换时的DOM操作错误

错误原因分析

  1. 元素获取失败:你尝试通过document.getElementById("aaa")获取的元素位于<template>标签内,模板内容默认不会被渲染到DOM中,因此初始获取到的是null,访问null的style属性就会抛出TypeError: Cannot read properties of null (reading 'style')。
  2. 重复ID问题:模板中的aaa、bbb、ccc是重复ID,克隆多个卡片后会违反HTML中ID唯一的规范,导致后续DOM操作混乱。
  3. 逻辑错误:全局控制元素显示隐藏的方式不适用,每个搜索结果卡片都是独立克隆的,需要针对每个卡片单独控制。

修正后的代码

HTML(修正重复ID问题)

<div class="search-container">
  <input type="search" id="search" data-search>
</div>
<div class="user-cards" data-user-cards-container></div>
<template data-user-template>
  <div class="card">
    <a href=""><div class="header" data-header></div></a>
    <div class="body_1" data-body_1></div>
    <div class="body_2" data-body_2></div>
    <div class="body_3" data-body_3></div>
  </div>
</template>

CSS(无需修改)

.user-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: .25rem;
  margin-top: 1rem;
}

.card {
  border: 0px solid black;
  background-color: white;
  padding: .5rem;
  text-align: center;
  font-size: 1.5rem;
}

.card > .header {
  margin-bottom: .25rem;
}

.card > .body_1 {
  font-size: 1rem;
  color: #777;
  font-weight: bold;
}

.card > .body_2 {
  font-size: 1rem;
  color: #777;
  font-weight: bold;
}

.card > .body_3 {
  font-size: 1rem;
  color: #777;
  font-weight: bold;
}

JavaScript(核心逻辑修正)

const userCardTemplate = document.querySelector("[data-user-template]")
const userCardContainer = document.querySelector("[data-user-cards-container]")
const searchInput = document.querySelector("[data-search]")

let users = []
let results = []

searchInput.addEventListener("input", e => {
  results = [];
  userCardContainer.innerHTML = "";

  const value = e.target.value.trim().toLowerCase()
  const xy = value.split(' ')

  // 先判断当前搜索模式
  let searchMode = 'text'; // 默认文本搜索
  if (xy.length === 3 && xy[0] === 'g') {
    searchMode = 'g-coord'; // g开头的坐标搜索
  } else if (xy.length === 2 && !isNaN(parseFloat(xy[0])) && !isNaN(parseFloat(xy[1]))) {
    searchMode = 'coord'; // 普通坐标搜索
  }

  if (value.length >= 4) {
    users.forEach(user => {
      let isVisible = false;
      let distance = null;
      const fvalue = value.replace("1", "9")

      // 根据搜索模式处理
      switch(searchMode) {
        case 'g-coord':
          // 计算g开头的距离
          distance = Math.sqrt(
            Math.pow(parseFloat(xy[1]) - parseFloat(user.x1), 2) +
            Math.pow(parseFloat(xy[2]) - parseFloat(user.y1), 2)
          )
          isVisible = distance <= 5;
          // 设置当前卡片的显示状态:显示body_2,隐藏1和3
          user.body_1.style.display = 'none';
          user.body_2.style.display = 'block';
          user.body_3.style.display = 'none';
          break;
        case 'coord':
          // 计算普通坐标距离
          distance = Math.sqrt(
            Math.pow(parseFloat(xy[0]) - parseFloat(user.x2), 2) +
            Math.pow(parseFloat(xy[1]) - parseFloat(user.y2), 2)
          )
          isVisible = distance <= 5;
          // 设置当前卡片的显示状态:显示body_3,隐藏1和2
          user.body_1.style.display = 'none';
          user.body_2.style.display = 'none';
          user.body_3.style.display = 'block';
          break;
        case 'text':
          // 文本搜索
          isVisible = user.mnames.includes(fvalue);
          // 设置当前卡片的显示状态:显示body_1,隐藏2和3
          user.body_1.style.display = 'block';
          user.body_2.style.display = 'none';
          user.body_3.style.display = 'none';
          break;
      }

      if (isVisible) {
        user.distance = distance;
        results.push(user);
      }
    })
  }
  
  // 排序并渲染结果
  results.sort((a, b) => (a.distance || 0) - (b.distance || 0))
  results.slice(0, 10).forEach(u => {
    userCardContainer.append(u.element);
  });
})

fetch("https://raw.githubusercontent.com/ucc23/ucc/main/_clusters/generated.json")
  .then(res => res.json())
  .then(data => {
    users = data.map(user => {
      const card = userCardTemplate.content.cloneNode(true).children[0]
      const header = card.querySelector("[data-header]")
      const body_1 = card.querySelector("[data-body_1]")
      const body_2 = card.querySelector("[data-body_2]")
      const body_3 = card.querySelector("[data-body_3]")
      card.querySelector("a").setAttribute("href", "https://url/" + user.name)

      header.textContent = user.name
      body_1.textContent = user.mnames.split(',')
      body_2.textContent = user.x1 + ',' + user.y1
      body_3.textContent = user.x2 + ',' + user.y2

      // 将body元素保存到user对象中,方便后续控制
      return {
        mnames: user.mnames,
        x1: user.x1,
        y1: user.y1,
        x2: user.x2,
        y2: user.y2,
        element: card,
        body_1,
        body_2,
        body_3
      }
    })
  })

关键改进点

  1. 移除重复ID:模板中的div不再使用重复ID,改用data属性选择,符合HTML规范。
  2. 保存元素引用:在生成user对象时,将每个卡片的body元素保存到对象中,避免全局获取的问题。
  3. 明确搜索模式:先判断当前输入对应的搜索模式,再针对每个模式处理显示逻辑,避免逻辑冲突。
  4. 单独控制卡片:每个卡片的显示状态独立设置,确保不同搜索模式下的卡片正确显示对应内容。

内容的提问来源于stack exchange,提问作者Gabriel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 09:14:56