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

ES5实现配色选择时的事件冒泡与父元素获取问题

解决配色选择器点击子元素不触发切换的问题

我明白你碰到的麻烦了:点击单选按钮、标签或者颜色块时没法切换配色,只有点击.scheme-color__option的空白区域才生效。这是因为你当前的代码只在event.target恰好是.scheme-color__option元素时才执行逻辑,但实际点击子元素时,target指向的是这些子节点,条件不满足自然就没反应。下面给你一步步解决的方案:

核心问题分析

你的事件委托绑定在.scheme-color__list上,这个思路本身没问题,但判断条件e.target.className === "scheme-color__option"太严苛——只有点击这个div本身的时候才会触发逻辑,而点击它内部的input、label或者td时,target是这些子元素,根本不会进入逻辑分支。

解决方案步骤

1. 实现ES5兼容的元素向上查找方法

因为ES5没有原生的Element.closest()方法,我们可以自己写一个函数,从触发事件的元素开始,向上查找最近的指定类名的父元素:

function findParentByClass(element, className) {
  while (element && element.nodeType === 1) {
    if (element.classList.contains(className)) {
      return element;
    }
    element = element.parentNode;
  }
  return null;
}

2. 修改事件处理逻辑

在点击事件里,用上面的函数找到真正的.scheme-color__option元素,而不是直接判断target:

schemeColorList.addEventListener('click', function(e) {
  // 找到当前点击元素所属的scheme-color__option
  var targetOption = findParentByClass(e.target, 'scheme-color__option');
  // 如果没找到匹配元素,直接返回
  if (!targetOption) return;

  // 移除所有选项的选中状态
  for (var j = 0; j < schemeColorOptions.length; j++) {
    var optionItem = schemeColorOptions[j];
    // 注意:div没有checked属性,要操作内部的input
    optionItem.querySelector('input').checked = false;
    optionItem.classList.remove('is-selected');
  }

  // 设置当前选项为选中状态
  targetOption.classList.add('is-selected');
  targetOption.querySelector('input').checked = true;

  // 获取当前选中的配色值
  var colorCells = targetOption.querySelectorAll('.scheme-color__palette td');
  var pColor = colorCells[0].style.backgroundColor;
  var sColor = colorCells[1].style.backgroundColor;
  var tColor = colorCells[2].style.backgroundColor;

  // 更新页面样式表
  var styleSheets = document.styleSheets;
  for (var i = 0; i < styleSheets.length; i++) {
    var rules = styleSheets[i].cssRules || styleSheets[i].rules;
    if (!rules) continue; // 跳过无权限访问的跨域样式表
    for (var j = 0; j < rules.length; j++) {
      switch(rules[j].selectorText) {
        case ".site-header":
          rules[j].style.backgroundColor = pColor;
          break;
        case ".site-nav":
          rules[j].style.backgroundColor = sColor;
          rules[j].style.borderColor = tColor;
          break;
        case ".site-nav__link:hover":
          rules[j].style.backgroundColor = pColor;
          break;
      }
    }
  }

  // 阻止事件冒泡(可选,若上层有其他点击事件冲突可启用)
  e.stopPropagation();
});

3. 修复原代码的小问题

  • 原代码里optionItem.checked = false是错误的,optionItem是div元素,没有checked属性,应该操作内部的input标签。
  • 获取颜色的循环可以简化,直接按索引取值即可,无需遍历所有颜色再赋值。
  • 遍历样式表时,加上if (!rules) continue可以避免跨域样式表的权限报错。

完整修改后的JS代码

// 自定义ES5兼容的父元素查找函数
function findParentByClass(element, className) {
  while (element && element.nodeType === 1) {
    if (element.classList.contains(className)) {
      return element;
    }
    element = element.parentNode;
  }
  return null;
}

var schemeColorList = document.querySelector('.scheme-color__list');
var schemeColorOptions = document.querySelectorAll('.scheme-color__option');

schemeColorList.addEventListener('click', function(e) {
  var targetOption = findParentByClass(e.target, 'scheme-color__option');
  if (!targetOption) return;

  // 重置所有选项状态
  for (var j = 0; j < schemeColorOptions.length; j++) {
    var option = schemeColorOptions[j];
    option.querySelector('input').checked = false;
    option.classList.remove('is-selected');
  }

  // 激活当前选中的选项
  targetOption.classList.add('is-selected');
  targetOption.querySelector('input').checked = true;

  // 获取配色值
  var colorCells = targetOption.querySelectorAll('.scheme-color__palette td');
  var pColor = colorCells[0].style.backgroundColor;
  var sColor = colorCells[1].style.backgroundColor;
  var tColor = colorCells[2].style.backgroundColor;

  // 更新页面样式
  var styleSheets = document.styleSheets;
  for (var i = 0; i < styleSheets.length; i++) {
    var rules = styleSheets[i].cssRules || styleSheets[i].rules;
    if (!rules) continue;
    for (var j = 0; j < rules.length; j++) {
      switch(rules[j].selectorText) {
        case ".site-header":
          rules[j].style.backgroundColor = pColor;
          break;
        case ".site-nav":
          rules[j].style.backgroundColor = sColor;
          rules[j].style.borderColor = tColor;
          break;
        case ".site-nav__link:hover":
          rules[j].style.backgroundColor = pColor;
          break;
      }
    }
  }

  e.stopPropagation();
});

这样修改后,不管你点击.scheme-color__option内部的任何元素(单选框、标签、颜色块),都会触发配色切换,同时也处理了事件冒泡的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:55:37