javascript - 如何使用组件更改 dom 元素
问题描述
import {
NotificationIcon,
SummaryIcon,
PublishIcon,
EngageIcon,
ListenIcon,
ReportIcon,
PlusIcon,
MinusIcon,
} from "../../icons/Icons";
import "./Sidebar.scss";
import ReactDOM from "react-dom";
const Sidebar = () => {
// handle accordion menu's open effect
const handleClassName = (arg) => {
const element = document.getElementById(arg);
element.classList.toggle("show");
element.firstElementChild.lastElementChild.remove()
};
const handleBrandsIcon = (arg) => {
const allBrands = document.querySelectorAll(".sidebar__brand");
for (let i = 0; i < allBrands.length; i++) {
allBrands[i].classList.remove("active");
document.getElementById(arg).classList.add("active");
}
};
const contentBox = [
{
id: 0,
icon: <SummaryIcon className="sidebar__icon" />,
label: "SUMMARY",
iconType: "summary",
},
{
id: 1,
icon: <PublishIcon className="sidebar__icon" />,
label: "PUBLISH",
iconType: "publish",
},
{
id: 2,
icon: <EngageIcon className="sidebar__icon" />,
label: "ENGAGE",
iconType: "engage",
},
{
id: 3,
icon: <ListenIcon className="sidebar__icon" />,
label: "LISTEN",
iconType: "listen",
},
{
id: 4,
icon: <ReportIcon className="sidebar__icon" />,
label: "REPORT",
iconType: "report",
},
];
const brands = [
{
img: "./gucci.gif",
id: 10,
},
{
img: "./coca-cola.gif",
id: 11,
},
{
img: "./pepsi.gif",
id: 12,
},
{
img: "./samsung.png",
id: 13,
},
{
img: "./tesla.gif",
id: 14,
},
{
img: "./twitter.png",
id: 15,
},
];
return (
<div className="sidebar">
<h2 className="sidebar__header">
sociality<label>.io</label>
</h2>
<div className="sidebar__wrapper">
<div className="sidebar__brands">
{brands.map((brand) => {
return (
<div
id={brand.id}
className="sidebar__brand"
onClick={() => handleBrandsIcon(brand.id)}
>
<img src={brand.img} className="sidebar__img" alt="/" />
</div>
);
})}
</div>
<div className="sidebar__accordion">
<div className="sidebar__content-box">
<div className="sidebar__row">
<NotificationIcon />
<label className="sidebar__label">NOTIFICATIONS</label>
<label className="sidebar__label sidebar__label--rounded">
28
</label>
</div>
<ul className="sidebar__list">
<li className="sidebar__item">Compase</li>
<li className="sidebar__item">Feed</li>
</ul>
</div>
{contentBox.map((content) => {
return (
<div
id={content.id}
className="sidebar__content-box"
onClick={() => handleClassName(content.id)}
>
<div className="sidebar__row">
{content.icon}
<label className="sidebar__label">{content.label}</label>
<PlusIcon className="sidebar__plus" />
</div>
<ul className="sidebar__list">
<li className="sidebar__item">Compase</li>
<li className="sidebar__item">Feed</li>
</ul>
</div>
);
})}
</div>
</div>
</div>
);
};
export default Sidebar;
嗨,伙计们有美好的一天。当我单击具有.sidebar__row
类名的 div 元素时,我想更改<PlusIcon/>
它<MinusIcon/>
。我将其推进到删除<PlusIcon/>
组件的阶段,但我无法以任何方式添加<MinusIcon/>
组件而不是<PlusIcon/>
。此外,我尝试添加ReactDOM.render(<MinusIcon className="sidebar__plus" /> , element.firstChild)
结束handleClassName
函数,我可以添加而不是但是这次所有子元素<div className="sidebar__row">
都被删除了。最后,如果你在我的代码中看到任何荒谬的东西,你可以给我建议,让我编写更干净的代码。
解决方案
添加状态以保存当前选定的品牌 ID,"active"
如果当前映射的品牌 ID 与状态匹配,则有条件地添加类。
添加状态以保存切换的内容 id 的映射,并有条件地在当前内容的 id 匹配上呈现无序列表和加号/减号图标。
contentBox
和数组是静态的brands
,因此它们可以从组件中拉出,在组件之外定义。
const contentBox = [.....];
const brands = [.....];
const Sidebar = () => {
const [showBrandId, setShowBrandId] = React.useState(null);
const [showContentIds, setShowContentIds] = React.useState({});
// handle accordion menu's open effect
const handleClassName = (contentId) => {
setShowContentIds(ids => ({
...ids,
[contentId]: !ids[contentId], // toggles boolean
}));
};
const handleBrandsIcon = (brandId) => {
setShowBrandId(brandId); // replaces current active brand
};
return (
<div className="sidebar">
<h2 className="sidebar__header">
sociality<label>.io</label>
</h2>
<div className="sidebar__wrapper">
<div className="sidebar__brands">
{brands.map((brand) => {
return (
<div
id={brand.id}
className={"sidebar__brand " + brand.id === showBrandId ? "active" : ""}
onClick={() => handleBrandsIcon(brand.id)}
>
<img src={brand.img} className="sidebar__img" alt="/" />
</div>
);
})}
</div>
<div className="sidebar__accordion">
<div className="sidebar__content-box">
<div className="sidebar__row">
<NotificationIcon />
<label className="sidebar__label">NOTIFICATIONS</label>
<label className="sidebar__label sidebar__label--rounded">
28
</label>
</div>
<ul className="sidebar__list">
<li className="sidebar__item">Compase</li>
<li className="sidebar__item">Feed</li>
</ul>
</div>
{contentBox.map((content) => {
const showContent = showContentIds[content.id];
return (
<div
id={content.id}
className={"sidebar__content-box" + showContent ? "show" : ""}
onClick={() => handleClassName(content.id)}
>
<div className="sidebar__row">
{content.icon}
<label className="sidebar__label">{content.label}</label>
{showContent ? (
<MinusIcon className="sidebar__minus" />
) : (
<PlusIcon className="sidebar__plus" />
)}
</div>
{showContent && (
<ul className="sidebar__list">
<li className="sidebar__item">Compase</li>
<li className="sidebar__item">Feed</li>
</ul>
)}
</div>
);
})}
</div>
</div>
</div>
);
};
推荐阅读
- javascript - 数字连接而不是相加
- ios - 解码自定义初始化中的所有属性(枚举类的所有属性并为其赋值)
- php - Google App Eng (flex) 上的 Symfony 4 - 500 错误
- html - Flexbox 在页面底部对齐一个元素中心和另一个元素
- r - geom_net 不会绘制网络的所有节点
- python - 使用 sympy 将向量值函数从 python 导出到 C
- javascript - 如何在使用 Cloud Functions 触发的事件上推送通知
- c - 循环内循环不运行
- list - 方案:将列表作为参数映射到函数
- php - 无法创建 MYSQL 主键