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

无法显示JavaScript DOM构建的HTML元素问题排查

QTrip首页城市卡片无法显示问题排查与修复

问题描述

我正在构建QTrip首页,需要从API获取城市数据并展示为城市卡片(预期效果为带有图片和文字的城市卡片列表),但当前页面无法显示任何城市卡片,仅展示导航栏、英雄区和页脚。

代码展示

HTML代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>QTrip</title>
    <link rel="stylesheet" href="css/styles.css" />
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
      crossorigin="anonymous"
    />
  </head>

  <body>
    <!-- Navigation bar -->
    <nav class="navbar navbar-expand-lg navbar-light bg-light ps-3">
      <a class="navbar-brand" href="#">QTrip</a>
      <button
        class="navbar-toggler"
        type="button"
        data-bs-toggle="collapse"
        data-bs-target="#navbarNavDropdown"
        aria-controls="navbarNavDropdown"
        aria-expanded="false"
        aria-label="Toggle navigation"
      >
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="navbarNavDropdown">
        <ul class="navbar-nav d-flex justify-content-end w-100">
          <li class="nav-item active">
            <a class="nav-link" href="#">Home</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="./pages/adventures/reservations/"
              >Reservations</a
            >
          </li>
        </ul>
      </div>
    </nav>

    <!-- Hero image section -->
    <div
      class="hero-image d-flex justify-content-center align-items-center text-white flex-column text-center"
    >
      <div class="container">
        <h1>Welcome to QTrip</h1>
        <p class="hero-subheading">
          Explore the world with fantastic places to venture around
        </p>
        <input class="hero-input" placeholder="Search a City" />
      </div>
    </div>

    <!-- Content section -->
    <div class="container">
      <div class="content text-white">
        <div class="row" id="data"></div>
      </div>
    </div>

    <!-- Footer section -->
    <footer>
      <div class="container">© QTrip 2020</div>
    </footer>

    <!-- Bootstrap script -->
    <script
      src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
      integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
      crossorigin="anonymous"
    ></script>

    <!-- Script for plugging in HTML of the Content section -->
    <script type="module">
      import { init } from "./modules/landing_page.js";

      //entry point (executed when DOM is loaded)
      (async function () {
        init();
      })();
    </script>
  </body>
</html>

JavaScript代码(modules/landing_page.js)

import { resourceLimits } from "worker_threads";
import config from "../conf/index.js";

async function init() {
  //Fetches list of all cities along with their images and description
  let cities = await fetchCities();

  //Updates the DOM with the cities
  cities.forEach((key) => {
    addCityToDOM(key.id, key.city, key.description, key.image);
  });

  console.log(config.backendEndpoint + "cities");
  console.log(cities);
}

//Implementation of fetch call
async function fetchCities() {
  // TODO: MODULE_CITIES
  // 1. Fetch cities using the Backend API and return the data
  try {
    let res = await fetch(config.backendEndpoint + "/cities");
    if (!res.ok) {
      throw Error(res.statusText);
    }
    let data = await res.json();
    return data;
  } catch (err) {
    //alert(err);
    return null;
  }
}

//Implementation of DOM manipulation to add cities
function addCityToDOM(id, city, description, image) {
  // TODO: MODULE_CITIES
  // 1. Populate the City details and insert those details into the DOM
  //Fetching the row container with id as data and putting the contents in it
  //column will go inside container having id data
  let column = document.createElement("div");
  column.className = "col-6 col-lg-3 mb-4";
  //explore will go inside column
  let explore = document.createElement("a");
  explore.id = id;
  explore.href = `pages/adventures/?city=${id}`;
  //tile container will go inside explore
  let tile = document.createElement("div");
  tile.className = "tile";
  //image1 will go inside anchor
  let image1 = document.createElement("img");
  image1.src = image;
  image1.className = "img-fluid rounded";
  image1.alt = "City Image";
  //tiletext will go inside card
  let tiletext = document.createElement("div");
  tiletext.className = "tile-text text-center";
  //cityname will go inside tiletext
  let cityname = document.createElement("h5");
  cityname.innerHTML = city;
  //carddescription will go inside tiletext
  let carddescription = document.createElement("p");
  carddescription.innerHTML = description;
  tiletext.append(cityname, carddescription);
  tile.append(image1, tiletext);
  explore.appendChild(tile);
  column.appendChild(explore);
  document.getElementById("data").appendChild(column);
}

export { init, fetchCities, addCityToDOM };

问题排查

  1. fetch失败后的处理漏洞:fetchCities函数在请求失败时返回null,但init函数直接调用cities.forEach,null没有forEach方法,会导致代码报错中断,无法执行DOM渲染逻辑。
  2. API地址有效性:需确认config.backendEndpoint是否正确,拼接后的config.backendEndpoint + "/cities"是否能正常访问并返回符合格式的JSON数组。
  3. 样式缺失:tile、tile-text等自定义类依赖css/styles.css,如果样式文件未正确加载或类定义缺失,会导致卡片存在但不可见(比如文字和图片重叠、背景色冲突)。
  4. API返回字段匹配:需确保API返回的每个城市对象包含id、city、description、image字段,字段名完全匹配,否则会导致图片加载失败或文字为空。
  5. 模块导入路径:确认../conf/index.js路径正确,且该文件正确导出了backendEndpoint配置项。

修复方案

1. 修复forEach报错问题

修改init函数,增加空值判断,避免报错中断:

async function init() {
  let cities = await fetchCities();
  // 检查数据是否存在
  if (!cities) {
    console.error("无法获取城市数据");
    return;
  }
  cities.forEach((key) => {
    addCityToDOM(key.id, key.city, key.description, key.image);
  });
  console.log(config.backendEndpoint + "/cities");
  console.log(cities);
}

2. 验证并修正API配置

  • 打开浏览器控制台,打印config.backendEndpoint确认地址正确性:在init函数中添加console.log(config.backendEndpoint),查看输出是否为有效的API地址。
  • 确保API返回格式为数组,示例返回数据:
[
  {
    "id": "paris",
    "city": "Paris",
    "description": "浪漫之都",
    "image": "https://example.com/paris.jpg"
  }
]

3. 补充必要的自定义样式

在css/styles.css中添加tile和tile-text的样式,确保卡片正常显示:

.tile {
  position: relative;
  overflow: hidden;
  border-radius: 8px;
  height: 250px;
}
.tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.tile-text {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: rgba(0,0,0,0.5);
  padding: 10px;
}
.tile-text h5 {
  margin: 0;
}
.tile-text p {
  margin: 5px 0 0;
  font-size: 14px;
}

4. 检查模块导入路径

确认conf/index.js文件存在,且内容如下:

export default {
  backendEndpoint: "https://your-actual-api-url.com"
};

5. 修复文字颜色冲突

content类设置了text-white,如果卡片背景透明,文字在白色背景上会看不见,可调整content的背景色,或修改tile-text的文字颜色确保可读性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 06:18:27