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

React中如何优雅遍历多分支缺失的JSON颜色数据?

设计系统中多分类颜色数据的优雅查找方案与React优化建议

问题背景

我是React新手,正在开发一套基于JSON配置的可复用设计系统,只需修改JSON参数就能在不同项目中复用。目前将普通颜色(可用于文本和背景)与链接颜色(仅用于文本)分两类存储,同时实现了ColorBox组件用于可视化展示可用颜色。

原组件代码

import React from "react";
import dataJSON from "../../../data/data.json";
import "./ColorBox.scss";

const colorsJSON = dataJSON.colors;
const linksJSON = dataJSON.links;

const ColorBox = (props) => {
    var myColor = colorsJSON.find((e) => e.var === props.var);

    // TODO: revise this, it is not decent code
    if (myColor === undefined) {
        myColor = linksJSON.find((e) => e.var === props.var);
    }

    return (
        <>
            <div className="colorbox">
                <div className="colorbox__name">{myColor.name}</div>
                <div className={`colorbox__color color-bg--${myColor.var}`}></div>
                <div className="colorbox__val">
                    <p>
                        <strong>{myColor.value}</strong>
                    </p>
                    <code>{myColor.var}</code>
                </div>
            </div>
        </>
    );
};

export default ColorBox;

JSON数据结构

{
  "colors": [
    {"value": "#fff", "var": "white", "name": "White"},
    {"value": "#f5f5f5", "var": "grey-l3", "name": "Very Light Grey"},
    {"value": "#eee", "var": "grey-l2", "name": "Light Grey"},
    {"value": "#ddd", "var": "grey-l1", "name": "Lightish Grey"},
    {"value": "#bbb", "var": "grey", "name": "Grey"},
    {"value": "#999", "var": "grey-d1", "name": "Darkish Grey"},
    {"value": "#666", "var": "grey-d2", "name": "Dark Grey"},
    {"value": "#333", "var": "grey-d3", "name": "Very Dark Grey"},
    {"value": "#000", "var": "black", "name": "Black"},
    {"value": "#68BBE3", "var": "primary-l2", "name": "Baby Blue"},
    {"value": "#0E86D4", "var": "primary-l1", "name": "Blue Grotto"},
    {"value": "#055C9D", "var": "primary", "name": "Blue"},
    {"value": "#003060", "var": "primary-d1", "name": "Navy Blue"},
    {"value": "#001040", "var": "primary-d2", "name": "Dark Navy Blue"},
    {"value": "#390", "var": "success", "name": "Success"},
    {"value": "#fc0", "var": "warn", "name": "Warning"},
    {"value": "#c30", "var": "fail", "name": "Failure"}
  ],
  "links": [
    {"value": "#00c", "var": "link", "name": "Link"},
    {"value": "#a4b", "var": "link-visited", "name": "Link Visited"},
    {"value": "#c30", "var": "link-active", "name": "Link Active"}
  ]
}

组件调用方式

<div className="box">
  <h2 className="h2 bold box__title">Accent</h2>
  <div className="box-palette__grid">
    <ColorBox var="success" />
    <ColorBox var="warn" />
    <ColorBox var="fail" />
  </div>
</div>
<div className="box">
  <h2 className="h2 bold box__title">Link values</h2>
  <div className="box-palette__grid">
    <ColorBox var="link" />
    <ColorBox var="link-visited" />
    <ColorBox var="link-active" />
  </div>
</div>

需求

当前通过判断colorsJSON查找结果是否为undefined来切换查找links分支的写法不够优雅,后续若新增背景色、图标色等更多颜色分类时会出现扩展性问题,希望得到更优的JSON数据遍历方案,以及React编程的优化建议。注:因设计系统中用途不同,links与colors无法合并为同一分类。


解决方案

一、优化数据查找方案

1. 预构建全局颜色映射表(推荐)

在组件外部提前将所有颜色分类合并为一个以var为键的映射对象,查找效率从O(n)提升到O(1),且新增分类时只需在数组中添加对应字段,完全不用修改查找逻辑:

import React from "react";
import dataJSON from "../../../data/data.json";
import "./ColorBox.scss";

// 预构建颜色映射表,新增分类时只需在数组中添加对应字段
const colorCategories = [dataJSON.colors, dataJSON.links];
const colorMap = colorCategories.flat().reduce((map, color) => {
  map[color.var] = color;
  return map;
}, {});

const ColorBox = (props) => {
  const myColor = colorMap[props.var];

  // 处理未找到颜色的边界情况,避免渲染报错
  if (!myColor) {
    return <div className="colorbox colorbox--error">未知颜色变量:{props.var}</div>;
  }

  return (
    <div className="colorbox">
      <div className="colorbox__name">{myColor.name}</div>
      <div className={`colorbox__color color-bg--${myColor.var}`}></div>
      <div className="colorbox__val">
        <p>
          <strong>{myColor.value}</strong>
        </p>
        <code>{myColor.var}</code>
      </div>
    </div>
  );
};

export default ColorBox;

2. 保留分类信息的映射方案(可选)

如果后续需要区分颜色所属分类,可以在构建映射时额外存储分类标识:

const colorMap = Object.entries(dataJSON).reduce((map, [category, colors]) => {
  colors.forEach(color => {
    map[color.var] = { ...color, category };
  });
  return map;
}, {});

此时myColor会包含category字段(如"colors"或"links"),方便后续实现分类相关的逻辑。


二、React编程优化建议

  • 替换var为const/let:原代码中var myColor改为const或let,避免变量提升带来的潜在问题,符合现代JavaScript规范。
  • 添加属性校验:使用PropTypes或TypeScript给props.var添加类型校验,提前发现无效传参:
    import PropTypes from 'prop-types';
    
    ColorBox.propTypes = {
      var: PropTypes.string.isRequired,
    };
    
  • 处理边界情况:新增未找到颜色时的降级渲染,避免因myColor为undefined导致的渲染崩溃,提升组件健壮性。
  • 简化组件结构:移除不必要的Fragment(<>),因为外层仅有一个div.colorbox节点,不需要额外包裹。
  • 抽离数据逻辑:将颜色映射逻辑抽离到单独的工具文件(如src/utils/colorUtils.js),便于其他组件复用,同时让ColorBox组件更专注于渲染逻辑:
    // src/utils/colorUtils.js
    import dataJSON from '../data/data.json';
    
    export const getColorMap = () => {
      return Object.entries(dataJSON).reduce((map, [category, colors]) => {
        colors.forEach(color => {
          map[color.var] = { ...color, category };
        });
        return map;
      }, {});
    };
    
    // ColorBox.js
    import { getColorMap } from '../utils/colorUtils';
    const colorMap = getColorMap();
    
  • 避免重复计算:颜色映射表在组件外部定义,不会随组件渲染重复计算,提升性能(即使当前数据量小,也能养成良好的代码习惯)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 10:35:21