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

TypeScript实现点击切换疫苗按钮颜色与文本状态

问题根因

现有代码仅在初始渲染时根据实例的vaccine属性生成对应样式的按钮,未绑定点击交互逻辑:点击后既不会修改实例的疫苗状态,也不会更新DOM显示,因此无法实现切换效果。

实现方案

采用事件委托实现点击切换,无需给每个按钮单独绑定事件,兼容排序后重绘的场景,性能更高,共3处修改:

  • 给所有类的displayInfo方法新增index入参,给疫苗按钮新增统一标识类vaccine-btn,同时绑定自定义属性data-index存储对应动物实例在数组中的下标
  • 修改cards渲染函数,遍历卡片时将数组索引传入displayInfo方法,每次渲染前先清空容器避免内容重复
  • 给卡片容器绑定点击事件,通过事件委托识别疫苗按钮点击,翻转对应实例的vaccine属性,直接更新按钮的样式和文本

注意:子类dogs和cats的displayInfo方法需要和基类做相同修改,否则子类渲染的按钮无法触发切换

关键修改代码
  1. 修改Animals基类的displayInfo方法,子类dogs、cats的displayInfo同步修改按钮部分即可:
// 基类displayInfo修改示例,子类同理
displayInfo(index: number) {
    return `
    <div class="col-lg-4 col-md-6 col-sm-12 d-flex justify-content-center">
        <div class="card card-decoration" style="width: 22rem;">
            <img src="${this.image}" class="card-img-top" style="height:25rem; object-fit:cover">
            <div class="card-title text-center bg-dark text-white p-1">${this.name}</div>
            <div class="card-body">
              <p class="card-text"><strong>Gender:</strong> ${this.gender}</p>
              <p class="card-text"><strong>Age:</strong> ${this.age}</p>
              <p class="card-text"><strong>Size:</strong> ${this.size}</p> 
              <!-- 新增vaccine-btn类和data-index属性 -->
              <h1 data-index="${index}" class="vaccine-btn text-center btn d-flex justify-content-center bg-${this.vaccine?"success":"danger"}">${this.vaccine?`Vaccinated <img src='../pics/tnailup.png' class='iconica'>`:`I need vaccine <img src='../pics/tnaildown.png' class='iconica'>`}</h1>
            </div>
          </div>
    </div>`;
}
  1. 修改cards渲染函数:
function cards() {
    const resultContainer = document.querySelector(".result") as HTMLElement;
    resultContainer.innerHTML = "";
    array.forEach((val, index) => {
        resultContainer.innerHTML += val.displayInfo(index);
    });
}
  1. 新增疫苗按钮点击逻辑,放在cards()调用前即可,原有年龄排序逻辑无需修改:
// 事件委托处理所有疫苗按钮点击
(document.querySelector(".result") as HTMLElement).addEventListener("click", (e) => {
    const target = e.target as HTMLElement;
    // 兼容点击按钮内部图片、文字的场景,向上查找疫苗按钮元素
    const vaccineBtn = target.closest(".vaccine-btn") as HTMLElement | null;
    if (!vaccineBtn) return;

    // 读取索引找到对应动物实例
    const animalIndex = Number(vaccineBtn.dataset.index);
    const currentAnimal = array[animalIndex];
    // 翻转疫苗状态
    currentAnimal.vaccine = !currentAnimal.vaccine;

    // 更新按钮样式
    vaccineBtn.classList.remove("bg-success", "bg-danger");
    vaccineBtn.classList.add(currentAnimal.vaccine ? "bg-success" : "bg-danger");
    // 更新按钮文本和图标
    vaccineBtn.innerHTML = currentAnimal.vaccine 
        ? `Vaccinated <img src='../pics/tnailup.png' class='iconica'>`
        : `I need vaccine <img src='../pics/tnaildown.png' class='iconica'>`;
});
效果说明
  • 初始加载时按钮状态与实例预设的vaccine属性一致
  • 点击按钮会在绿色已接种、红色待接种两种状态间循环切换,对应文本、图标同步更新
  • 年龄排序后重绘的卡片无需重新绑定事件,点击功能正常
  • 仅更新被点击的按钮元素,无需重绘整个卡片列表,无页面卡顿

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 15:57:27