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

如何用TypeScript实现项目列表展示与搜索及类编写验证?

项目管理Web应用实现方案

需求概述

我正在开发一个简单Web应用,用于查看所有项目并按名称搜索项目:

  • 打开浏览器时展示所有项目
  • 添加搜索文本框,输入内容时从JSON文件过滤数据

现有资源

JSON数据(project.json)

{
  "projects": [
    { "id": 1, "name" : "Project 1" },
    { "id": 2, "name" :"Command 2" },
    { "id": 3, "name" :"Project 3" },
    { "id": 4, "name" :"Project 4" }
  ]
}

初始TypeScript类代码

class Project {
   private id?: number;
   private name?: string;
}

class ProjectFactory {
    getAllProjects(){
    }

    searchProject(){
    }
}

HTML页面代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="style.css">
    <script src="product.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script>
</head>
    <body>
        <div class="container">
            <nav class="navbar navbar bg-dark" data-bs-theme="dark">
                <div class="container-fluid">
                    <a class="navbar-brand" href="#">Embla - Product Management Software</a>
                    <img src="/images/img_avatar.png" alt="Avatar" class="avatar">
                </div>
            </nav>
            <br>
            <input class="form-control" type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names.." title="Type in a name">
    
            <table class="table" id="myTable">
                <thead class="table-dark">
                  <tr>
                    <th style="width:50%;">Id</th>
                    <th style="width:50%;">Project Name</th>
                  </tr>
                </thead>
                <tbody>
                    <tr>
                        <td>1</td>
                        <td>Project 1</td>
                    </tr>
                    <tr>
                        <td>2</td>
                        <td>Command 2</td>
                    </tr>
                    <tr>
                        <td>3</td>
                        <td>Project 3</td>
                    </tr>
                    <tr>
                        <td>4</td>
                        <td>Project 4</td>
                    </tr>
                </tbody>
              </table>
        </div>
   </body>
</html>

示例TypeScript代码

class Project {
  id!:number;
  name!:string;
 
  constructor(id:number, name:string) {
    this.id=id;
    this.name=name;
  }
} 

class ProjectFactory {
  // Example of method
  getName() : string {
    let p = new Project(1, "A");
    return p.id + " "+ p.name
  }
}

let project = new ProjectFactory(); 

console.log(project.getName());

解决方案

1. TypeScript类的正确写法

调整后的类保证类型安全、数据封装及逻辑单一性:

// Project实体类,用构造函数参数简化属性定义,设为只读避免外部修改
class Project {
  constructor(public readonly id: number, public readonly name: string) {}
}

// ProjectFactory负责数据加载、存储与搜索逻辑
class ProjectFactory {
  private projects: Project[] = [];

  // 从JSON文件异步加载项目数据
  async loadProjects(): Promise<void> {
    const response = await fetch('project.json');
    const data = await response.json();
    this.projects = data.projects.map((item: { id: number; name: string }) => 
      new Project(item.id, item.name)
    );
  }

  // 返回所有项目的副本,防止外部修改内部数据
  getAllProjects(): Project[] {
    return [...this.projects];
  }

  // 按名称模糊搜索(大小写不敏感)
  searchProjects(searchTerm: string): Project[] {
    const lowerTerm = searchTerm.toLowerCase();
    return this.projects.filter(project => 
      project.name.toLowerCase().includes(lowerTerm)
    );
  }
}

2. 加载JSON数据并渲染到HTML

编写DOM渲染逻辑,确保页面加载时自动加载并展示项目:

const projectFactory = new ProjectFactory();
const tableBody = document.querySelector('#myTable tbody') as HTMLTableSectionElement;

// 将项目列表渲染到表格
function renderProjects(projects: Project[]) {
  tableBody.innerHTML = '';
  projects.forEach(project => {
    const row = document.createElement('tr');
    row.innerHTML = `
      <td>${project.id}</td>
      <td>${project.name}</td>
    `;
    tableBody.appendChild(row);
  });
}

// 页面DOM加载完成后初始化数据
window.addEventListener('DOMContentLoaded', async () => {
  await projectFactory.loadProjects();
  renderProjects(projectFactory.getAllProjects());
});

3. 实现搜索功能

替换原有搜索函数,绑定输入框事件实现实时过滤:

// 处理搜索输入
function handleSearch() {
  const searchInput = document.querySelector('#myInput') as HTMLInputElement;
  const searchTerm = searchInput.value.trim();
  const filteredProjects = projectFactory.searchProjects(searchTerm);
  renderProjects(filteredProjects);
}

修改HTML中输入框的事件绑定:

<input class="form-control" type="text" id="myInput" onkeyup="handleSearch()" placeholder="Search for names.." title="Type in a name">

4. 文件连接与部署注意事项

  • TypeScript编译:使用tsc project.ts命令将TypeScript编译为JavaScript(需先通过npm install -g typescript安装TypeScript)
  • 脚本引用:将HTML中的<script src="product.js"></script>改为<script src="project.js"></script>(对应编译后的JS文件名),并将脚本标签移到</body>前,确保DOM加载完成后执行
  • 本地测试:需使用HTTP服务器(如npx serve)启动项目,不能直接打开HTML文件,否则会因跨域限制导致fetch请求失败

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 18:33:25