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

PHP项目:JSON人员数据展示的视图切换功能实现求助

问题描述

我需要开发一个程序,实现从JSON文件读取人员数据并展示的功能:默认视图只显示人员姓名,点击任意一项后切换为该人员的完整信息(姓名、电话、邮箱)。目前无法实现视图切换,以下是我的代码:

HTML代码

<html>
<head>
    <link rel="stylesheet" type="text/css" href="style.css">
    <script type="text/javascript" src="skript.js"></script>
    <title>Main</title>
</head>
<body>
    <header>
        <h1>Main</h1>
    </header>
    </nav>
    <main class="view">
    </main>     
</body>
</html>

JS代码

fetch('data.json')
    .then(response => response.json())
    .then(data => createListContact(data));

/**
* Function to display as a list data.json
*/
function createListContact(data) {
    // create ol for all persons
    const ol = document.createElement('ol');
    ol.classList.add("list-view");

    // for each person one li 
    for (let i = 0; i < data.personen.length; i++) {
        const li = document.createElement('li');
        li.classList.add("button");
        li.setAttribute("id", i+1);
        li.innerHTML ='Name: '+ data.personen[i].nachname + ', ' + data.personen[i].vorname;
        
        ol.appendChild(li);
        document.body.appendChild(ol);
    }
}
       
/*
* Function adds event listener to li element
*/
function eventListener (){
    const liElements = document.getElementsByTagName("li");
    for (let li of liElements){
        li.addEventListener("click",() => showDetails(li));
    }
}

/** 
*  Function to open detailed info
*
*   @param li element to show details from
*/
function showDetails(li){
    var details = document.createElement('div');
    details.className = 'details';
    details.id ="test";

    var close = document.createElement('div');
    close.className= 'close';
    close.innerHTML= 'close';
    close.onclick = function(e) { details.parentNode.removeChild(details)};
    var info = document.createElement('li');
    info.innerHTML = 'Name: '+ data.personen[i].nachname + ', ' + data.personen[i].vorname +
    'Tel.: '+ data.personen[i].telefonnummer+
    'E-mail: '+data.personen[i].email;
    details.appendChild(info);
    details.appendChild(schließen);
    document.body.appendChild(details);
}

CSS代码

body {
    background-color: #886b6b77;
}       
p {
    color: #333;
    font-family: "Times New Roman", Times, serif;
    font-size: 20px;
    text-align: center;
}
textarea
{
    font-family: inherit;    
}

form {
    border: 1px solid black;
    width: 90%;
    background-color: whitesmoke;
    margin: 0 auto;
    padding: 0 1em;
}

form label {
    display: block;
    font-size: 0.8em;
    color: darkslategrey;
    padding-left: 3px;    
}

input,
textarea
{
    width: 100%;
    font-size: 1.1em; 
    padding: 4px;
    font-family: inherit;
    font-weight: lighter;
    border:1px solid gray;
    outline: none;
    border-radius: 0.3em;
}    

input:focus,
textarea:focus { 
    border:1px solid orange;
}

input[type=submit] {
    background-color: #ffffff77;
    cursor: pointer;
    width: 14em;
    padding: .3em 0;
    border-radius: 0.7em;
    margin-bottom: 1em;
}

input[type=submit]:hover {
    background-color: rgb(59, 58, 58);
    box-shadow: 2px 2px 2px grey;
}
ul {
    list-style-type: none;
    margin: 0;
    padding: 0;
    overflow: hidden;
    background-color: #333;
    margin-bottom: 1em;
}

ul li {
    float: left;
}

li a {
    display: block;
    color: white;
    text-align: center;
    padding: 14px 16px;
    text-decoration: none;
}
ol{
    list-style-type: none;
    text-align: center;
    color: white;
}
/* Change the link color to #111 (black) on hover */
li a:hover {
    background-color: #111;
}
img{
    display: block;
    margin-left: auto;
    margin-right: auto;
    width: 50%;
}
#wahl{
    margin-top: 1em;
    margin-bottom: 0.5em;
}
#button_load{
    margin-bottom: 1em;
}

/*
* list-view
*/
.list-view .button {
    cursor: pointer;
    background: none;
    font-size: 20px;
    color: white;
    font-family: "Times New Roman", Times, serif;
}
.list-view .button:hover{
    background-color: #333;
}

问题修复方案

核心问题梳理

  1. 事件监听器未触发:eventListener()函数仅定义未调用,导致点击事件未绑定。
  2. 数据作用域失效:showDetails无法访问createListContact内的data和i变量。
  3. DOM重复插入:循环内多次将<ol>插入body,应该循环结束后统一插入。
  4. 变量名错误:schließen应为close。
  5. 视图切换逻辑缺失:未隐藏列表视图,仅追加详情元素。

修复后的完整代码

HTML(修正多余标签)

<html>
<head>
    <link rel="stylesheet" type="text/css" href="style.css">
    <script type="text/javascript" src="skript.js"></script>
    <title>Main</title>
</head>
<body>
    <header>
        <h1>Main</h1>
    </header>
    <nav></nav>
    <main class="view">
    </main>     
</body>
</html>

JS(修复所有问题)

// 全局存储人员数据,方便详情函数访问
let personData = [];

fetch('data.json')
    .then(response => response.json())
    .then(data => {
        personData = data.personen;
        createListContact(data);
        // 创建列表后立即绑定事件
        eventListener();
    });

/**
* 生成人员列表视图
*/
function createListContact(data) {
    const ol = document.createElement('ol');
    ol.classList.add("list-view");

    for (let i = 0; i < data.personen.length; i++) {
        const li = document.createElement('li');
        li.classList.add("button");
        // 存储索引,方便后续获取对应数据
        li.dataset.index = i;
        li.innerHTML = `Name: ${data.personen[i].nachname}, ${data.personen[i].vorname}`;
        ol.appendChild(li);
    }
    // 循环结束后统一插入到main容器
    document.querySelector('.view').appendChild(ol);
}
       
/**
* 为列表项绑定点击事件
*/
function eventListener (){
    const liElements = document.querySelectorAll(".list-view .button");
    liElements.forEach(li => {
        li.addEventListener("click", () => showDetails(li));
    });
}

/** 
* 显示人员详情视图
*/
function showDetails(li){
    // 获取当前项对应的人员索引
    const index = parseInt(li.dataset.index);
    const person = personData[index];

    // 清空main容器,切换视图
    const main = document.querySelector('.view');
    main.innerHTML = '';

    // 创建详情容器
    const details = document.createElement('div');
    details.className = 'details';

    // 创建返回按钮
    const backBtn = document.createElement('button');
    backBtn.className = 'back-btn';
    backBtn.textContent = '返回列表';
    backBtn.addEventListener('click', () => {
        main.innerHTML = '';
        createListContact({personen: personData});
        eventListener();
    });

    // 创建详情内容
    const info = document.createElement('div');
    info.innerHTML = `
        <h2>${person.nachname}, ${person.vorname}</h2>
        <p>Tel.: ${person.telefonnummer}</p>
        <p>E-mail: ${person.email}</p>
    `;

    details.appendChild(backBtn);
    details.appendChild(info);
    main.appendChild(details);
}

CSS(新增详情视图样式)

body {
    background-color: #886b6b77;
}       
p {
    color: #333;
    font-family: "Times New Roman", Times, serif;
    font-size: 20px;
    text-align: center;
}
textarea
{
    font-family: inherit;    
}

form {
    border: 1px solid black;
    width: 90%;
    background-color: whitesmoke;
    margin: 0 auto;
    padding: 0 1em;
}

form label {
    display: block;
    font-size: 0.8em;
    color: darkslategrey;
    padding-left: 3px;    
}

input,
textarea
{
    width: 100%;
    font-size: 1.1em; 
    padding: 4px;
    font-family: inherit;
    font-weight: lighter;
    border:1px solid gray;
    outline: none;
    border-radius: 0.3em;
}    

input:focus,
textarea:focus { 
    border:1px solid orange;
}

input[type=submit] {
    background-color: #ffffff77;
    cursor: pointer;
    width: 14em;
    padding: .3em 0;
    border-radius: 0.7em;
    margin-bottom: 1em;
}

input[type=submit]:hover {
    background-color: rgb(59, 58, 58);
    box-shadow: 2px 2px 2px grey;
}
ul {
    list-style-type: none;
    margin: 0;
    padding: 0;
    overflow: hidden;
    background-color: #333;
    margin-bottom: 1em;
}

ul li {
    float: left;
}

li a {
    display: block;
    color: white;
    text-align: center;
    padding: 14px 16px;
    text-decoration: none;
}
ol{
    list-style-type: none;
    text-align: center;
    color: white;
    padding: 0;
}
/* Change the link color to #111 (black) on hover */
li a:hover {
    background-color: #111;
}
img{
    display: block;
    margin-left: auto;
    margin-right: auto;
    width: 50%;
}
#wahl{
    margin-top: 1em;
    margin-bottom: 0.5em;
}
#button_load{
    margin-bottom: 1em;
}

/*
* list-view
*/
.list-view .button {
    cursor: pointer;
    background: none;
    font-size: 20px;
    color: white;
    font-family: "Times New Roman", Times, serif;
    padding: 8px 0;
    border-bottom: 1px solid rgba(255,255,255,0.2);
}
.list-view .button:hover{
    background-color: #333;
}

/*
* 详情视图样式
*/
.details {
    background-color: rgba(255,255,255,0.9);
    padding: 2em;
    border-radius: 8px;
    max-width: 600px;
    margin: 2em auto;
    color: #333;
}

.back-btn {
    background-color: #333;
    color: white;
    border: none;
    padding: 8px 16px;
    border-radius: 4px;
    cursor: pointer;
    margin-bottom: 1em;
}

.back-btn:hover {
    background-color: #111;
}

.details h2 {
    font-family: "Times New Roman", Times, serif;
    margin-bottom: 1em;
}

.details p {
    text-align: left;
    margin: 0.5em 0;
}

关键修改说明

  1. 全局存储数据:用personData变量存储人员数据,让showDetails能访问到完整信息。
  2. 绑定事件时机:在fetch回调中创建列表后立即调用eventListener,确保事件绑定有效。
  3. 存储索引:给列表项添加data-index属性,点击时能快速定位到对应人员数据。
  4. 视图切换逻辑:点击列表项时清空main容器,替换为详情内容;点击返回按钮时重新渲染列表。
  5. 修复DOM插入错误:循环内只创建列表项,循环结束后将整个<ol>插入到main容器。
  6. 新增详情样式:添加详情视图的CSS,提升页面美观度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 00:42:03