如何以更DRY的方式条件性应用CSS类?
优化方案:符合DRY原则的实现
嘿,这个重复代码的问题确实挺常见的,咱们可以通过抽象判断逻辑+统一管理类名的方式来优化,既能减少冗余,后续维护也更方便。
第一步:统一管理所有CSS类
先把所有可能用到的类名存成一个数组,这样移除类的时候不用反复罗列,改类名也只需要改这一处:
const ALL_CLASSES = ['active', 'before', 'previous', 'next', 'after'];
第二步:把类名判断逻辑抽成单独函数
把原来分散在遍历里的if判断集中到一个函数里,逻辑更清晰,也避免重复写判断条件:
function getTargetClass(index, currentState) { if (index === currentState) return 'active'; if (index === currentState - 1) return 'previous'; if (index === currentState + 1) return 'next'; if (index < currentState - 1) return 'before'; if (index > currentState + 1) return 'after'; return ''; // 无匹配情况返回空 }
第三步:简化遍历逻辑
现在遍历的时候,只需要调用上面的函数拿到类名,统一移除所有类再添加目标类就行:
const children2 = Array.from(wrapper.children); const currentState = state.state; children2.forEach((child, i) => { // 一次性移除所有可能的类 child.classList.remove(...ALL_CLASSES); // 获取当前元素对应的类名 const targetClass = getTargetClass(i, currentState); // 有类名就添加 if (targetClass) { child.classList.add(targetClass); } });
进阶优化:用映射表替代if判断
如果后续要加更多类名规则,用映射表会比一堆if更直观,扩展性也更强:
function getTargetClass(index, currentState) { // 用Map存储条件和类名的对应关系 const classRules = new Map([ [() => index === currentState, 'active'], [() => index === currentState - 1, 'previous'], [() => index === currentState + 1, 'next'], [() => index < currentState - 1, 'before'], [() => index > currentState + 1, 'after'], ]); // 找到第一个满足的条件,返回对应类名 for (const [condition, className] of classRules) { if (condition()) return className; } return ''; }
这样以后要加新规则,直接在classRules里加一行就行,不用动判断逻辑的结构,非常方便。
为什么这符合DRY原则?
- 避免了重复书写类名列表(移除类的时候不用反复写那一串类名)
- 把分散的条件判断集中到一处,不用在遍历循环里堆一堆
if - 后续修改类名或者添加新状态规则,只需要改一个地方,不用到处调整
内容的提问来源于stack exchange,提问作者Himmators
相关产品推荐
相关产品推荐

