【问题标题】:React- onClick styling of currentTarget当前目标的 React-onClick 样式
【发布时间】:2018-01-10 03:44:34
【问题描述】:

我正在尝试构建一个简单的动态更新的交互式列表,当您单击它们时,根据 .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 机器 react 提供的功能?

如果你知道这个问题是重复的,请留下评论,我会删除它。

【问题讨论】:

  • 被点击的&lt;li&gt; 是唯一获得clicked 类的人吗
  • 是的,这就是全部挑战。
  • 正确,但即使点击更多,它是否保留点击的类?
  • 是的。我理解你答案的第一部分(你能详细说明为什么不使用 map 的索引作为键吗?)但是我觉得第二部分有点抽象:假设我使用 state 来收集所有已经被到目前为止在数组等数据结构中单击。我不是必须在某些时候使用 vanilla js 才能真正改变他们的课程吗?
  • 我不认为你不应该,你能从地图上发布一个样本x 对象吗...我很好奇它的样子。我正在编写一些要添加的代码,我可以使用更多关于 this.props.sentences 的详细信息来进一步实现这一点

标签: reactjs onclick styles


【解决方案1】:

1) 我有这种感觉对吗? (我的解决方案不是最佳实践?)

假设这不是一个理想的方法是正确的,在 React 中通过 vanilla js 操作 DOM 有它的位置 (Example Use Cases) 但除非绝对必要,否则不应这样做。此外,使用来自 Array.prototype.map 的索引作为组件上的键并不理想,因为如果它们更改顺序可能会导致 React 混淆,因为在这种情况下键的映射方式会有所不同。

2) (如果是,)我如何构建我的代码以使用虚拟 dom 机器 react 提供的功能?

您应该使用组件状态。如果您希望每个单击的元素都保持clicked 类,那么创建一个状态来缓存已经收到clicked 类的元素。如果只有最近单击的元素获得clicked 类,则只需将标识符缓存到状态中的适当元素。您也可以为此目的使用refs,尽管 facebook 不鼓励过度使用它们。

这是一个快速剪辑,它将在每个 &lt;li&gt; 上切换 click

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>
        );
    }
}

【讨论】:

  • 我在这里获取我们的 conv 以供参考。句子可以是任何东西,最基本的形式是 ["a","b","c"];这将生成一个包含三个 li 元素的列表。我认为你是正确的,我不应该使用 map 中的索引作为键。但是,如果道具不断更新,我应该使用什么?
  • 一般来说,不应该使用索引作为来自Array.prototype.map 调用的键,除非在映射的数组中不能保证是唯一的(例如使用对象的唯一属性或如果它们的值是唯一的,那么使用该值是可以接受的。
  • 在这种情况下,在不知道this.props.sentences 是什么的情况下,我确实选择使用索引作为每个
  • 的键
  • 很好地使用了模板文字。今晚我将进一步研究答案和可能性。 ty
  • 没问题,兄弟,请随意点击接受按钮;)。编码愉快!
  • 猜你喜欢
    相关资源
    最近更新 更多
    热门标签