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

JavaScript点击事件中值的添加与移除逻辑问题求助

问题:比赛结果点击切换时球队数据无法正确回滚

我有两个表格,一个用于展示球队对象及其数据,另一个是供用户点击的比赛选项表格,点击后可修改前者的球队数据。首次点击时数据变更正常,但再次点击时无法正确回滚数据:例如点击win单元格时,首次会为主队增加3分和1场胜利,但再次点击时无法扣除对应的分数和胜场。

现有代码示例

数据定义

let teams = [
    {name: 'Roma', points: 0, wins: 0, draws: 0, loses: 0},
    {name: 'Atalanta', points: 0, wins: 0, draws: 0, loses: 0},
    {name: 'Milan', points: 0, wins: 0, draws: 0, loses: 0},
    {name: 'Fiorentina', points: 0, wins: 0, draws: 0, loses: 0},
]
let matches = [
    // Round 1.
    {homeName: teams[0].name, teamHome: 0, win: '', draw: '', awayTeamWin: '', teamAway: 1, awayName: teams[1].name},
    {homeName: teams[2].name, teamHome: 2, win: '', draw: '', awayTeamWin: '', teamAway: 3, awayName: teams[3].name},
    // Round 2.
    {homeName: teams[0].name, teamHome: 0, win: '', draw: '', awayTeamWin: '', teamAway: 2, awayName: teams[2].name},
    {homeName: teams[1].name, teamHome: 1, win: '', draw: '', awayTeamWin: '', teamAway: 3, awayName: teams[3].name},
    // Round 3.
    {homeName: teams[0].name, teamHome: 0, win: '', draw: '', awayTeamWin: '', teamAway: 3, awayName: teams[3].name},
    {homeName: teams[1].name, teamHome: 1, win: '', draw: '', awayTeamWin: '', teamAway: 2, awayName: teams[2].name},
]

分数统计函数

function matchWinnerTeamPoints(matchWinner) {
    matchWinner.points += 3;
    matchWinner.wins ++;
}
function matchLoserTeamPoints(matchLoser) {
    matchLoser.loses ++;
}
function matchDrawPoints(teamHome, teamAway) {
    teamHome.points ++;
    teamAway.points ++;
    teamHome.draws ++;
    teamAway.draws ++;
}

比赛表格渲染与点击事件

function createMatchesTable(matchesTableBody, matches) {
    cleaner(matchesTableBody);
    // 原代码省略循环逻辑,仅保留关键点击事件部分
    let win = bodyRow.insertCell(-1);
    if (match.win === true) {
        win.className = 'bg-success';
    }
    win.onclick = (e) => {
        match.draw = '';
        match.awayTeamWin = '';
        match.win = !match.win;
        createMatchesTable(matchesTableBody, matches);
        matchWinnerTeamPoints(teams[match.teamHome]);
        matchLoserTeamPoints(teams[match.teamAway]);
        cleaner(createStandingTable(standingTableBody, teams));
    }
}

问题根源

  1. 无回滚逻辑:现有代码只实现了"加分/增加统计"的正向操作,完全没有处理"取消结果时扣除数据"的反向逻辑,导致再次点击时只会继续累加数据。
  2. 状态判断混乱:match对象的状态初始值为字符串'',和布尔值true混合使用,容易导致判断错误;且未处理之前可能设置过的其他结果(比如先点了平局,再点主队胜时,没有回滚平局的统计)。

解决方法

1. 新增回滚函数

为每种比赛结果编写对应的反向回滚逻辑,与正向统计函数对应:

// 保留原有正向函数
function matchWinnerTeamPoints(matchWinner) {
    matchWinner.points += 3;
    matchWinner.wins++;
}
function matchLoserTeamPoints(matchLoser) {
    matchLoser.loses++;
}
function matchDrawPoints(teamHome, teamAway) {
    teamHome.points++;
    teamAway.points++;
    teamHome.draws++;
    teamAway.draws++;
}

// 新增回滚函数
function rollbackWinnerPoints(matchWinner) {
    matchWinner.points -= 3;
    matchWinner.wins--;
}
function rollbackLoserPoints(matchLoser) {
    matchLoser.loses--;
}
function rollbackDrawPoints(teamHome, teamAway) {
    teamHome.points--;
    teamAway.points--;
    teamHome.draws--;
    teamAway.draws--;
}

2. 修改点击事件逻辑

遵循先回滚旧状态,再应用新状态的流程,同时统一状态为布尔值:

function createMatchesTable(matchesTableBody, matches) {
    cleaner(matchesTableBody);
    
    // 遍历所有比赛,补充完整循环逻辑
    matches.forEach(match => {
        let bodyRow = matchesTableBody.insertRow();
        // 插入主客场队名等其他单元格的逻辑...
        
        let win = bodyRow.insertCell(-1);
        win.textContent = '主队胜';
        // 统一用布尔值判断状态
        if (match.win === true) {
            win.className = 'bg-success';
        }
        
        win.onclick = (e) => {
            const homeTeam = teams[match.teamHome];
            const awayTeam = teams[match.teamAway];
            
            // 第一步:回滚当前比赛已有的结果
            if (match.win) {
                // 当前是选中状态,点击取消,回滚主队胜数据
                rollbackWinnerPoints(homeTeam);
                rollbackLoserPoints(awayTeam);
            } else if (match.draw) {
                // 之前是平局,切换为主队胜,先回滚平局数据
                rollbackDrawPoints(homeTeam, awayTeam);
            } else if (match.awayTeamWin) {
                // 之前是客队胜,切换为主队胜,先回滚客队胜数据
                rollbackWinnerPoints(awayTeam);
                rollbackLoserPoints(homeTeam);
            }
            
            // 第二步:更新比赛状态,清空其他结果
            match.draw = false;
            match.awayTeamWin = false;
            match.win = !match.win;
            
            // 第三步:如果新状态为选中,应用正向统计
            if (match.win) {
                matchWinnerTeamPoints(homeTeam);
                matchLoserTeamPoints(awayTeam);
            }
            
            // 重新渲染表格
            createMatchesTable(matchesTableBody, matches);
            createStandingTable(standingTableBody, teams);
        };
        
        // 平局(draw)和客队胜(awayTeamWin)的点击逻辑参考上述实现,注意角色互换
    });
}

3. 初始化状态修正

将matches数组中所有结果的初始值改为布尔值false,避免类型判断问题:

let matches = [
    // Round 1.
    {homeName: teams[0].name, teamHome: 0, win: false, draw: false, awayTeamWin: false, teamAway: 1, awayName: teams[1].name},
    {homeName: teams[2].name, teamHome: 2, win: false, draw: false, awayTeamWin: false, teamAway: 3, awayName: teams[3].name},
    // ...其他比赛项同理修改
]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 00:10:25