React.js - 如何创建Accordeon(与兄弟姐妹交谈)

时间:2015-02-03 15:48:53

标签: javascript accordion reactjs

我刚开始使用react.js,我喜欢组件的工作方式。我创建了一个Card组件,它会在点击时添加一个css-class expanded。这就像一个魅力。现在,我希望所有其他卡片在点击另一张卡片后松开expanded属性。在jQuery中,我使用siblings来执行此操作。

react.js的正确解决方案是什么?

这是我的代码:

var Card = React.createClass({

    getInitialState: function () {
        return {
            expanded: false,
            //clickCount: 0
        };
    },

    handleClick: function (event) {
        this.setProps({expanded: !this.props.expanded});
    },

    render: function () {
        var cx = React.addons.classSet;
        var classes = cx({
            'card': true,
            'expanded': this.state.expanded
        });

        return (
            <li className={classes} onClick={this.handleClick}>
                <h1>{this.props.name}</h1>
                <h2>{this.props.entf.toFixed(2)} km</h2>
            </li>
        )
    }

});


var App = React.createClass({

    handleClick: function (event) {
        console.log("clicked");
    },

    render: function () {

        var pools = this.props.data.map(function (pool) {
            return (
                <Card onClick={this.handleClick} name={pool.name} entf={pool.entf} />
            );
        });

        return (<ul>
                {pools}
        </ul>
        )
    }
});

2 个答案:

答案 0 :(得分:2)

您应该在siblings组件的App中为扩展卡保留一个标识符,而不是使用state,如果所选卡片发生更改,则让React重新渲染。

以下是一个如何使用react做的示例:

JSfiddle:http://jsfiddle.net/vdw27xpf/

var Card = React.createClass({

    render: function () {
        var cx = React.addons.classSet;
        var classes = cx({
            'card': true,
            'expanded': this.props.expanded
        });

        return (
            <li className={classes} onClick={this.props.onClick}>
                <h1>{this.props.name}</h1>
                <h2>{this.props.entf.toFixed(2)} km</h2>
            </li>
        )
    }

});


var App = React.createClass({

    getInitialState : function(){
        return { expandedCardName : null };
    },

    handleClick: function (value) {
       this.setState({ expandedCardName : value });
    },

    render: function () {

        var pools = this.props.data.map(function (pool) {
            return (
                <Card key={pool.name}
                      expanded = { pool.name == this.state.expandedCardName }
                      onClick={this.handleClick.bind(this,pool.name)} 
                      name={pool.name} entf={pool.entf} />
            );
        }.bind(this));

        return (<ul>
                {pools}
            </ul>
        )
    }
});
var data = [ { name:"card1", entf:60 },{ name:"card2", entf:50 } ]; 
React.render(<App data={data} />, document.body);

答案 1 :(得分:0)

React不是超级吗?

为了获得您想要的行为而不进行太多修改,我建议将回调onClickonExpand传递给每个<Card/>。当激活卡时,它会运行回调,该回调可以在应用程序的状态中设置变量(可能是activeCard)。在App的渲染方法中,修改map函数,为每张卡片赋予expanded布尔道具,这取决于卡片的名称/ ID是否与activeCard匹配。在每张卡片的逻辑中使用新的expanded道具代替this.state.expanded

var Card = React.createClass({

render: function () {
    var cx = React.addons.classSet;
    var classes = cx({
        'card': true,
        'expanded': this.props.expanded
    });

    return (
        <li className={classes} onClick={this.props.onClick}>
            <h1>{this.props.name}</h1>
            <h2>{this.props.entf.toFixed(2)} km</h2>
        </li>
    )
}

});


var App = React.createClass({

getInitialState: function () {
    return { activeCard: '' }
},

render: function () {

    var pools = this.props.data.map(function (pool) {
        return (
            <Card onClick={this.handleClick.bind(this,pool.name)} name={pool.name} entf={pool.entf} expanded={pool.name == this.state.activeCard} />
        );
    }.bind(this));

    return (<ul>
            {pools}
    </ul>
    )
},

handleClick: function (value) {
    this.setState({ activeCard: value })
}
});

在React工作时,请考虑如何将组件保持为尽可能无状态。在像jQuery这样的范例中,这些部分经常自我管理,但如果你想使用React的潜力,那么请时刻注意如何“涓滴”状态。