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

如何为innerHTML创建元素绑定按钮功能 实现章节操作与localStorage存取

解决思路与完整实现

核心问题原因

你当前遇到的动态生成按钮失效问题,是因为直接通过querySelector获取元素绑定事件,仅作用于页面初始化时已存在的DOM,后续动态插入的元素不会自动绑定该事件。我们采用事件委托方案解决:将事件绑定到页面始终存在的父容器(如.main),通过判断触发事件的元素类名执行对应逻辑,可覆盖所有动态生成的元素。

完整修改代码

HTML代码

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="/css/style.css">
    <link rel="stylesheet" href="/css/normalize.css">
    <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>JavaScript</title>
    <style>
        /* 删除按钮基础样式,可自行调整 */
        .btn-del-chapter, .btn-del-item {
            margin-left: 10px;
            color: red;
            border: 1px solid red;
            background: #fff;
            cursor: pointer;
        }
        .btn-save {
            margin-left: 10px;
            background: #2ecc71;
            color: #fff;
            border: none;
            padding: 4px 8px;
            cursor: pointer;
        }
    </style>
</head>
<body class='main'>

<button class="btn-new-chapter">Add New Chapter</button>
<button class="btn-save">Save Data</button>
<ol class="main-body">
    <ul class="chapter-list">
        <li class="chapter-list-title">
            <div class="data">
                <h1 class="title">
                    <input type="text" class="chapter-title" placeholder="Chapter Title">
                    <button class="btn-del-chapter">删除整个章节</button>
                </h1>
                <button class="btn-add-chapter">Add Body Text</button>
                <button class="btn-add-sub-chapter">Add SubBody Text</button>
            </div>
        </li>
    </ul>

    <ul class="chapter-list-body">
        <li class="chapter-list-text">
            <div class="chapter">
                <input type="text" class="chapter-text" placeholder="Chapter Body">
                <button class="btn-del-item">删除</button>
            </div>
        </li>
    </ul>
</ol>
<script src="/scripts/script.js"></script>
</body>
</html>

JS代码

'use strict';

const main = document.querySelector('.main');
let appData = [];

// 事件委托:统一处理所有按钮点击,覆盖所有动态生成元素
main.addEventListener('click', function(e) {
    const target = e.target;
    // 获取当前按钮所属的章节容器
    const currentChapter = target.closest('.main-body');
    const currentChapterBody = currentChapter?.querySelector('.chapter-list-body');

    // 1. 新增整个章节
    if (target.classList.contains('btn-new-chapter')) {
        const ol = document.createElement('ol');
        ol.classList.add('main-body');
        ol.innerHTML = `<ul class="chapter-list">
                        <li class="chapter-list-title">
                        <div class="data">
                        <h1 class="title">
                        <input type="text" class="chapter-title" placeholder="Chapter Title">
                        <button class="btn-del-chapter">删除整个章节</button>
                        </h1>
                        <button class="btn-add-chapter">Add Body Text</button>
                        <button class="btn-add-sub-chapter">Add SubBody Text</button>
                        </div>
                        </li>
                        </ul>
                        <ul class="chapter-list-body">
                        <li class="chapter-list-text">
                        <div class="chapter">
                        <input type="text" class="chapter-text" placeholder="Chapter Body">
                        <button class="btn-del-item">删除</button>
                        </div>
                        </li>
                        </ul>`;
        main.append(ol);
    }

    // 2. 新增正文项
    if (target.classList.contains('btn-add-chapter')) {
        const li = document.createElement('li');
        li.classList.add('chapter-list-text');
        li.innerHTML = `<div class="chapter">
                        <input type="text" class="chapter-text" placeholder="Chapter Body">
                        <button class="btn-del-item">删除</button>
                        </div>`;
        currentChapterBody.append(li);
    }

    // 3. 新增子章节项
    if (target.classList.contains('btn-add-sub-chapter')) {
        const li = document.createElement('li');
        li.classList.add('sub-chapter-list-text');
        li.innerHTML = `<div class="subchapter">
                        <input type="text" class="sub-chapter-text" placeholder="SubChapter Body">
                        <button class="btn-del-item">删除</button>
                        </div>`;
        currentChapterBody.append(li);
    }

    // 4. 删除整个章节
    if (target.classList.contains('btn-del-chapter')) {
        currentChapter.remove();
    }

    // 5. 删除单个正文/子章节项
    if (target.classList.contains('btn-del-item')) {
        target.closest('li').remove();
    }

    // 6. 保存数据到localStorage
    if (target.classList.contains('btn-save')) {
        const allChapters = document.querySelectorAll('.main-body');
        const saveData = [];
        allChapters.forEach(chapter => {
            const title = chapter.querySelector('.chapter-title').value;
            const items = [];
            chapter.querySelectorAll('.chapter-list-body li').forEach(item => {
                if (item.classList.contains('chapter-list-text')) {
                    items.push({
                        type: 'chapter',
                        value: item.querySelector('.chapter-text').value
                    })
                } else if (item.classList.contains('sub-chapter-list-text')) {
                    items.push({
                        type: 'subChapter',
                        value: item.querySelector('.sub-chapter-text').value
                    })
                }
            })
            saveData.push({
                title: title,
                items: items
            })
        })
        localStorage.setItem('chapterData', JSON.stringify(saveData));
        alert('数据保存成功');
    }
})

// 页面初始化时读取localStorage渲染数据
window.addEventListener('load', function() {
    const saveData = localStorage.getItem('chapterData');
    if (!saveData) return;
    const data = JSON.parse(saveData);
    // 清空默认初始章节
    main.innerHTML = `<button class="btn-new-chapter">Add New Chapter</button>
    <button class="btn-save">Save Data</button>`;
    // 渲染所有存储的章节
    data.forEach(chapter => {
        let itemsHtml = '';
        chapter.items.forEach(item => {
            if (item.type === 'chapter') {
                itemsHtml += `<li class="chapter-list-text">
                            <div class="chapter">
                            <input type="text" class="chapter-text" placeholder="Chapter Body" value="${item.value}">
                            <button class="btn-del-item">删除</button>
                            </div>
                            </li>`
            } else {
                itemsHtml += `<li class="sub-chapter-list-text">
                            <div class="subchapter">
                            <input type="text" class="sub-chapter-text" placeholder="SubChapter Body" value="${item.value}">
                            <button class="btn-del-item">删除</button>
                            </div>
                            </li>`
            }
        })
        const ol = document.createElement('ol');
        ol.classList.add('main-body');
        ol.innerHTML = `<ul class="chapter-list">
                        <li class="chapter-list-title">
                        <div class="data">
                        <h1 class="title">
                        <input type="text" class="chapter-title" placeholder="Chapter Title" value="${chapter.title}">
                        <button class="btn-del-chapter">删除整个章节</button>
                        </h1>
                        <button class="btn-add-chapter">Add Body Text</button>
                        <button class="btn-add-sub-chapter">Add SubBody Text</button>
                        </div>
                        </li>
                        </ul>
                        <ul class="chapter-list-body">
                        ${itemsHtml}
                        </ul>`;
        main.append(ol);
    })
})

实现说明

  • 所有按钮事件都通过父容器.main委托实现,动态生成的元素无需单独绑定事件即可生效
  • 保存数据时会自动遍历所有章节的标题、正文、子章节内容,结构化存储到localStorage的chapterData字段
  • 页面刷新后会自动读取本地存储的内容,完整还原章节结构和输入值
  • 删除功能支持删除单个正文/子章节项,也支持删除整个章节,操作后点击保存即可同步到本地存储

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 05:09:01