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

基于localStorage的待办App自定义优先级排序实现求助

修复localStorage待办App的自定义优先级排序功能

需求与问题

  • 需求逻辑:将所有任务两两对比,用户点击偏好的任务后对应counter数组索引值+1,完成所有对比后按计数排序
  • 当前问题:
    • 嵌套for循环未等待用户点击就执行完毕,仅显示最后一组任务
    • 点击事件重复绑定,导致点击某任务时多个索引值同时递增

修正后的HTML代码

<!-- LogRocket code -->
<div class="container">
    <div class="to-do-app">
        <h2>To-do App</h2>
        <br>
        <input type="text" id="item" placeholder="Enter item...">
        <br><br>
        <button onclick="add()">Add Item <i class="fa-solid fa-plus"></i></button>
        <button onclick="del()">Clear all <i class="fa-solid fa-ban"></i></button>
    </div>
    <ul class="to-do-list"></ul>
<!-- end of LogRocket code -->
<!-- 自定义优先级功能代码 -->
    <button onclick="prioritize()">Prioritize</button>
    <div class="comparison-container">
        <div id="task1" class="task-option"><i class="fa-solid fa-circle-plus"></i><span></span></div>
        <div id="task2" class="task-option"><i class="fa-solid fa-circle-plus"></i><span></span></div>
        <div id="comparison-status"></div>
    </div>
</div>
<script src="./script.js"></script>

补充CSS样式(对比区域)

/* 新增对比区域样式 */
.comparison-container {
    margin-top: 20px;
    display: flex;
    gap: 20px;
    flex-direction: column;
    align-items: center;
}
.task-option {
    background-color: whitesmoke;
    padding: 15px 20px;
    border-radius: 5px;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 10px;
}
.task-option:hover {
    background-color: rgba(0, 0, 0, 0.1);
}
#comparison-status {
    margin-top: 10px;
    font-size: small;
    color: #666;
}

修正后的JavaScript代码

// 基础待办功能(LogRocket原代码)
const ul = document.querySelector('ul');
const input = document.getElementById('item');
let itemsArray = localStorage.getItem('items') ? JSON.parse(localStorage.getItem('items')) : [];
let counter = [];

// 提前缓存DOM元素引用
const task1 = document.getElementById("task1");
const task2 = document.getElementById("task2");
const task1Span = task1.querySelector('span');
const task2Span = task2.querySelector('span');
const statusText = document.getElementById('comparison-status');

itemsArray.forEach(addTask);
function addTask(text) {
    const li = document.createElement('li');
    li.textContent = text;
    ul.appendChild(li);
}
function add() {
    if (!input.value.trim()) return;
    itemsArray.push(input.value);
    localStorage.setItem('items', JSON.stringify(itemsArray));
    addTask(input.value);
    input.value = '';
}

function del() {
    localStorage.clear();
    ul.innerHTML = '';
    itemsArray = [];
}

// 封装等待用户点击的Promise函数
function waitForTaskClick(taskElement, index) {
    return new Promise((resolve) => {
        const handleClick = () => {
            counter[index] += 1;
            console.log(`Item ${index + 1} = ${counter[index]}`);
            // 点击后移除事件,避免重复触发
            taskElement.removeEventListener('click', handleClick);
            resolve();
        };
        taskElement.addEventListener('click', handleClick);
    });
}

// 修正后的优先级排序逻辑
async function prioritize() {
    if (itemsArray.length < 2) {
        alert("至少需要2个任务才能进行优先级对比");
        return;
    }

    // 重置计数器
    counter = new Array(itemsArray.length).fill(0);
    console.log('计数器已重置:', counter);

    // 生成不重复的两两对比组合(避免A→B和B→A重复对比)
    const comparisons = [];
    for (let j = 0; j < itemsArray.length; j++) {
        for (let k = j + 1; k < itemsArray.length; k++) {
            comparisons.push([j, k]);
        }
    }

    // 逐个处理对比组合
    for (let i = 0; i < comparisons.length; i++) {
        const [index1, index2] = comparisons[i];
        // 更新当前对比的任务文本
        task1Span.textContent = itemsArray[index1];
        task2Span.textContent = itemsArray[index2];
        statusText.textContent = `对比 ${i + 1}/${comparisons.length}: 选择更优先的任务`;

        // 等待用户点击任意一个任务,再进行下一组对比
        const clickPromise1 = waitForTaskClick(task1, index1);
        const clickPromise2 = waitForTaskClick(task2, index2);
        await Promise.race([clickPromise1, clickPromise2]);
    }

    // 对比完成后按计数器降序排序任务
    statusText.textContent = "对比完成,正在排序...";
    const sortedItems = itemsArray
        .map((item, index) => ({ item, count: counter[index] }))
        .sort((a, b) => b.count - a.count)
        .map(obj => obj.item);

    // 更新localStorage和页面列表
    itemsArray = sortedItems;
    localStorage.setItem('items', JSON.stringify(itemsArray));
    ul.innerHTML = '';
    itemsArray.forEach(addTask);
    statusText.textContent = "优先级排序完成!";
}

关键修复说明

  1. 异步流程控制:用async/await结合Promise实现等待用户点击的逻辑,解决循环提前执行完毕的问题
  2. 事件绑定优化:每次对比时绑定新的点击事件,点击后立即移除,避免事件累加导致的多次计数
  3. 避免重复对比:仅生成j < k的任务组合,不会重复对比同一对任务
  4. 自动更新UI:完成所有对比后自动排序任务,并同步更新localStorage和页面列表
  5. 用户反馈:添加对比状态文本,让用户清晰了解当前对比进度

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 00:05:41