React.js中如何根据数组cName值动态创建组件替代className
styled-components 替换 className 遍历绑定实现方案
要实现完全基于styled-components、去掉className硬编码的效果,根据你的场景可以按以下方式实现:
基础场景(当前所有菜单项cName一致)
你贴出的MenuItems配置里所有项的cName都是dropdown-link,这种情况最简单,直接把对应类的样式封装成styled版本的Link组件,替换原来带className的Link即可:
- 封装样式组件
import styled from 'styled-components'; import { Link } from 'react-router-dom'; const DropdownLink = styled(Link)` /* 这里写原dropdown-link类的全部CSS样式 */ display: block; padding: 0.5rem 1rem; color: #333; text-decoration: none; &:hover { background: #f5f5f5; } `;
- 替换渲染逻辑
{MenuItems.map((item, index) => { return ( <WrapperLi key={index}> <DropdownLink to={item.path} onClick={() => setClick(false)} > {item.title} </DropdownLink> </WrapperLi> ); })}
多cName场景(后续存在不同样式菜单项)
如果后续菜单项会有不同cName对应不同样式,用组件映射表的方式实现,不需要改动遍历的核心逻辑:
- 封装所有cName对应的styled组件,建立映射关系
import styled from 'styled-components'; import { Link } from 'react-router-dom'; // 不同cName对应不同样式组件 const DropdownLink = styled(Link)` /* dropdown-link 对应样式 */ display: block; padding: 0.5rem 1rem; color: #333; &:hover { background: #f5f5f5; } `; const TopNavLink = styled(Link)` /* 后续新增的nav-link对应样式 */ color: #fff; display: flex; align-items: center; height: 100%; `; // cName和组件的映射表 const linkComponentMap = { 'dropdown-link': DropdownLink, 'nav-link': TopNavLink };
- 遍历的时候根据item.cName取对应组件渲染即可
{MenuItems.map((item, index) => { // 匹配不到对应组件时默认用基础Link兜底 const ActiveLink = linkComponentMap[item.cName] || Link; return ( <WrapperLi key={index}> <ActiveLink to={item.path} onClick={() => setClick(false)} > {item.title} </ActiveLink> </WrapperLi> ); })}
轻量差异场景(不同cName样式差异很小)
如果不同cName对应的样式只有少量属性差异,不需要单独建多个组件,可以给styled组件传props动态控制样式:
- 写支持props的动态样式组件
import styled, { css } from 'styled-components'; import { Link } from 'react-router-dom'; const StyledMenuLink = styled(Link)` /* 所有链接通用基础样式 */ text-decoration: none; padding: 0.5rem 1rem; /* 根据传入的linkType匹配差异化样式 */ ${({ linkType }) => linkType === 'dropdown-link' && css` color: #333; display: block; &:hover { background: #f5f5f5; } `} ${({ linkType }) => linkType === 'top-nav' && css` color: #fff; height: 100%; display: flex; align-items: center; `} `;
- 把MenuItems里的cName字段改成语义化的类型字段,渲染时直接传props即可
{MenuItems.map((item, index) => { return ( <WrapperLi key={index}> <StyledMenuLink to={item.path} linkType={item.type} onClick={() => setClick(false)} > {item.title} </StyledMenuLink> </WrapperLi> ); })}
内容的提问来源于stack exchange,提问作者user19024715
相关产品推荐
相关产品推荐

