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
相关产品推荐
相关产品推荐

