在 React 中单击时,如何防止所有手风琴组件被切换?
How can I prevent all of my accodion components being toggled when clicked in React?
我创建了一个自定义 Accordion 组件,它又由两个 child 组件组成,分别称为 AccordionTitle
和 AccordionContent
:
AccordionTitle
组件有一个按钮。单击时,AccordionContent
部分将其样式从 display:none
切换到 block
,然后再次单击时返回。
AccordionTitle.js
class AccordionTitle extends Component {
constructor() {
super();
this.show = false;
}
toggle() {
this.show = !this.show;
if (this.props.onToggled) this.props.onToggled(this.show);
}
render() {
return (
<div style={this.props.style}>
<Button onClick={e => this.toggle(e)} />
{this.props.children}
</div>
);
}
}
export default AccordionTitle;
AccordionContent.js
class AccordionContent extends Component {
render() {
let style = this.props.style ? this.props.style : {};
style = JSON.parse(JSON.stringify(style));
style.display = this.props.show ? 'block' : 'none';
return (
<div style={style}>
{this.props.children}
</div>
);
}
}
export default AccordionContent;
此外,我使用以下 parent 组件:
Accordion.js
class Accordion extends Component {
render() {
return (
<div>
{this.props.children}
</div>
);
}
}
Accordion.Title = AccordionTitle;
Accordion.Content = AccordionContent;
export default Accordion;
现在,当我使用手风琴组件时,我可能需要连续使用多个手风琴,如下所示:
产品Accordion.js
import React, { Component } from 'react';
import Accordion from '../Accordion/Accordion';
class ProductAccordion extends Component {
constructor() {
super();
this.state = {
show: false,
};
}
toggled() {
this.setState({
show: !this.state.show,
});
}
render() {
this.productsJsx = [];
const products = this.props.products;
for (let i = 0; i < products.length; i += 1) {
this.productsJsx.push(
<Accordion.Title onToggled={e => this.toggled(e, this)}>
{products[i].name}
<img src="{products[i].imgsrc}" />
</Accordion.Title>,
<Accordion.Content show={this.state.show}>
{products[i].name}<br />
{products[i].grossprice} {products[i].currency}<br />
<hr />
</Accordion.Content>,
);
}
return (
<Accordion style={styles.container}>
{this.productsJsx}
</Accordion>
);
}
}
export default ProductAccordion;
如您所见,我正在从 Accordion.Title
获取 toggled
事件,并通过 [=24= 将其绑定到 Accordion.Content
的属性 show
]方法。
现在,只要只有一种产品,它就可以正常工作,但如果有更多产品,单击按钮将切换所有 AccordionContent
个实例。
如何更改此设置,以便仅切换属于包含单击按钮的标题的 content-part?
我也觉得组件 Accordion
应该通过允许 Accordion.Title
将 toggled
事件直接委托给来处理这个(而不是 ProductAccordion
)它的兄弟 Accordion.Content
。我怎样才能做到这一点?
我建议将未清项目的索引存储在状态中,而不是布尔值。然后在您的渲染中,show={this.state.show}
将类似于 show={this.state.show === i}
.
完整示例:
import React, { Component } from 'react';
import Accordion from '../Accordion/Accordion';
class ProductAccordion extends Component {
constructor() {
super();
this.state = {
show: null,
};
}
toggled(event, ind) {
const index = this.state.index;
this.setState({ show:ind === index ? null : ind });
}
render() {
this.productsJsx = [];
const products = this.props.products;
for (let i = 0; i < products.length; i += 1) {
this.productsJsx.push(
<Accordion.Title onToggled={e => this.toggled(e, i)}>
{products[i].name}
<img src="{products[i].imgsrc}" />
</Accordion.Title>,
<Accordion.Content show={this.state.show === i}>
{products[i].name}<br />
{products[i].grossprice} {products[i].currency}<br />
<hr />
</Accordion.Content>,
);
}
return (
<Accordion style={styles.container}>
{this.productsJsx}
</Accordion>
);
}
}
export default ProductAccordion;
还有这个
class AccordionTitle extends Component {
constructor() {
super();
}
render() {
return (
<div style={this.props.style}>
<Button onClick={this.props.onToggled} />
{this.props.children}
</div>
);
}
}
export default AccordionTitle;
我创建了一个自定义 Accordion 组件,它又由两个 child 组件组成,分别称为 AccordionTitle
和 AccordionContent
:
AccordionTitle
组件有一个按钮。单击时,AccordionContent
部分将其样式从 display:none
切换到 block
,然后再次单击时返回。
AccordionTitle.js
class AccordionTitle extends Component {
constructor() {
super();
this.show = false;
}
toggle() {
this.show = !this.show;
if (this.props.onToggled) this.props.onToggled(this.show);
}
render() {
return (
<div style={this.props.style}>
<Button onClick={e => this.toggle(e)} />
{this.props.children}
</div>
);
}
}
export default AccordionTitle;
AccordionContent.js
class AccordionContent extends Component {
render() {
let style = this.props.style ? this.props.style : {};
style = JSON.parse(JSON.stringify(style));
style.display = this.props.show ? 'block' : 'none';
return (
<div style={style}>
{this.props.children}
</div>
);
}
}
export default AccordionContent;
此外,我使用以下 parent 组件:
Accordion.js
class Accordion extends Component {
render() {
return (
<div>
{this.props.children}
</div>
);
}
}
Accordion.Title = AccordionTitle;
Accordion.Content = AccordionContent;
export default Accordion;
现在,当我使用手风琴组件时,我可能需要连续使用多个手风琴,如下所示:
产品Accordion.js
import React, { Component } from 'react';
import Accordion from '../Accordion/Accordion';
class ProductAccordion extends Component {
constructor() {
super();
this.state = {
show: false,
};
}
toggled() {
this.setState({
show: !this.state.show,
});
}
render() {
this.productsJsx = [];
const products = this.props.products;
for (let i = 0; i < products.length; i += 1) {
this.productsJsx.push(
<Accordion.Title onToggled={e => this.toggled(e, this)}>
{products[i].name}
<img src="{products[i].imgsrc}" />
</Accordion.Title>,
<Accordion.Content show={this.state.show}>
{products[i].name}<br />
{products[i].grossprice} {products[i].currency}<br />
<hr />
</Accordion.Content>,
);
}
return (
<Accordion style={styles.container}>
{this.productsJsx}
</Accordion>
);
}
}
export default ProductAccordion;
如您所见,我正在从 Accordion.Title
获取 toggled
事件,并通过 [=24= 将其绑定到 Accordion.Content
的属性 show
]方法。
现在,只要只有一种产品,它就可以正常工作,但如果有更多产品,单击按钮将切换所有 AccordionContent
个实例。
如何更改此设置,以便仅切换属于包含单击按钮的标题的 content-part?
我也觉得组件 Accordion
应该通过允许 Accordion.Title
将 toggled
事件直接委托给来处理这个(而不是 ProductAccordion
)它的兄弟 Accordion.Content
。我怎样才能做到这一点?
我建议将未清项目的索引存储在状态中,而不是布尔值。然后在您的渲染中,show={this.state.show}
将类似于 show={this.state.show === i}
.
完整示例:
import React, { Component } from 'react';
import Accordion from '../Accordion/Accordion';
class ProductAccordion extends Component {
constructor() {
super();
this.state = {
show: null,
};
}
toggled(event, ind) {
const index = this.state.index;
this.setState({ show:ind === index ? null : ind });
}
render() {
this.productsJsx = [];
const products = this.props.products;
for (let i = 0; i < products.length; i += 1) {
this.productsJsx.push(
<Accordion.Title onToggled={e => this.toggled(e, i)}>
{products[i].name}
<img src="{products[i].imgsrc}" />
</Accordion.Title>,
<Accordion.Content show={this.state.show === i}>
{products[i].name}<br />
{products[i].grossprice} {products[i].currency}<br />
<hr />
</Accordion.Content>,
);
}
return (
<Accordion style={styles.container}>
{this.productsJsx}
</Accordion>
);
}
}
export default ProductAccordion;
还有这个
class AccordionTitle extends Component {
constructor() {
super();
}
render() {
return (
<div style={this.props.style}>
<Button onClick={this.props.onToggled} />
{this.props.children}
</div>
);
}
}
export default AccordionTitle;