我正在尝试构建一个简单的动态更新的交互式列表,根据.clicked类的css规则对每个<li></li>
进行样式设置,当您单击它们时。
该应用程序由两个组件组成,父项和子项,所讨论的代码如下(取自孩子):
handleClick(e) {
document.getElementById(e.currentTarget.id).setAttribute("class","clicked");
}
render() {
let ar = this.props.sentences;
let pro = ar.map((x,i)=>{ return (<li id={i} key={i} className={i%2==0 ? "white" : "grey"}
onClick={this.handleClick}>{x}</li>); })
return (
<div>
<ul id="ul">{ pro }</ul>
</div>
这里发生的事情基本上是父母将一个句子传递给孩子(一系列句子将形成动态列表的基础)。
有争议的部分是我以document.getElementById(e.currentTarget.id).setAttribute("class","two");
的形式使用DOM操作,以便从jsx更改动态创建的html的类。
上面的代码,但它不是最佳做法。使用react的全部优势是使用虚拟dom并优化DOM的更新方式。
我的问题如下:
1)我是否有这种感觉? (我的解决方案不是最佳做法?)
2)(如果是这样,)我如何构建我的代码以便使用虚拟dom机器做出反应?
如果您知道此问题是重复的,请发表评论,我会将其删除。
答案 0 :(得分:2)
1)我是否有这种感觉? (我的解决方案不是最佳做法?)
假设这不是一种理想的方法是正确的,在React中通过vanilla js操纵DOM有它的位置(Example Use Cases)但除非绝对必要,否则不应该这样做。此外,使用Array.prototype.map
中的索引作为组件上的键是不理想的,就像它们改变顺序一样,它可能会导致React混淆,因为在这种情况下键会以不同的方式映射。
2)(如果是这样,)我如何构建我的代码以便使用虚拟dom机器反应提供?
您应该使用组件状态。如果您希望每个单击的元素都维护clicked
类,那么创建一个状态来缓存已经收到clicked
类的元素。如果只有最近点击的元素获得clicked
类,则只需将标识符缓存到状态中的相应元素。你也可以使用refs来达到这个目的,虽然facebook有些不鼓励他们的过度使用。
这是一个快速剪切,可以切换每个click
<li>
课程
class Test extends Component {
constructor() {
super();
this.state = {
clicked: {}
};
}
render() {
let ar = this.props.sentences;
let pro = ar.map((x, i) => {
const color_class = i % 2 === 0 ? "white" : "grey";
const clicked_class = this.state.clicked[i] === true ? "clicked" : "";
let clicked = Object.assign({}, this.state.clicked); // Dont mutate state!!!
return (
<li
id={i}
key={i}
className={`${color_class} ${clicked_class}`}
onClick={e => {
if (clicked.hasOwnProperty(i)) {
delete clicked[i];
} else {
clicked[i] = true;
}
this.setState({ clicked });
}}
>
{x}
</li>
);
});
return (
<div>
<ul id="ul">
{pro}
</ul>
</div>
);
}
}