在Bootstrap popover中渲染React组件

Fre*_*ton 29 jquery twitter-bootstrap reactjs

我有一组使用bootstrap popover ui组件在内容属性/参数中使用popovers的图像我想添加ReactJS MusicList组件,但我无法弄清楚语法或是否可能.

var MusicList = React.createClass({
    render : function(){
        return(<ul><li>Here</li></ul>);
    }
});

var PopoverImage = React.createClass({
    componentDidMount:function(){

        $("#"+this.getDOMNode().id).attr('data-component','<span>here</span>');
        $("#"+this.getDOMNode().id).popover({
            html:true,
            content: 
            });
    },

    render:function(){
        return(
            <img href="#" id={this.props.friend.uid+'_popover'} data-html={true} className="smallImage" src={this.props.friend.pic_small} rel="popover" data-original-title={this.props.friend.name} />

                );
    }
});
Run Code Online (Sandbox Code Playgroud)

Sop*_*ert 39

Bootstrap不易在弹出窗口中渲染动态组件.如果你想要呈现的popover是静态的,你可以简单地使用React's renderComponentToString,它接受一个组件并通过回调返回一个HTML字符串:

var html = React.renderComponentToString(<MusicList />);
$(this.getDOMNode()).popover({
    html: true,
    content: html
});
Run Code Online (Sandbox Code Playgroud)

但是,如果您的组件具有任何交互性,则该策略将不起作用,因为React从未有机会附加事件处理程序(或运行任何自定义生命周期方法).实际上,Bootstrap没有提供正确的钩子来使你的popover内容动态化.


也就是说,可以通过修补Bootstrap来完成这项工作.我创建了一个具有动态弹出内容的实时演示:

popover演示截图
http://jsfiddle.net/spicyj/q6hj7/

请注意,当前时间在弹出窗口中由每秒更新的React组件呈现.


这个popover是如何创建的?

我修补了Bootstrap popover的setContent方法以获取除HTML或文本字符串之外的React组件.我没有使用jQuery htmltext方法,而是使用React.renderComponent:

// Patch Bootstrap popover to take a React component instead of a
// plain HTML string
$.extend($.fn.popover.Constructor.DEFAULTS, {react: false});
var oldSetContent = $.fn.popover.Constructor.prototype.setContent;
$.fn.popover.Constructor.prototype.setContent = function() {
    if (!this.options.react) {
        return oldSetContent.call(this);
    }

    var $tip = this.tip();
    var title = this.getTitle();
    var content = this.getContent();

    $tip.removeClass('fade top bottom left right in');

    // If we've already rendered, there's no need to render again
    if (!$tip.find('.popover-content').html()) {
        // Render title, if any
        var $title = $tip.find('.popover-title');
        if (title) {
            React.renderComponent(title, $title[0]);
        } else {
            $title.hide();
        }

        React.renderComponent(content,  $tip.find('.popover-content')[0]);
    }
};
Run Code Online (Sandbox Code Playgroud)

现在你可以写了

$(this.getDOMNode()).popover({
    react: true,
    content: <MusicList />
});
Run Code Online (Sandbox Code Playgroud)

在您的componentDidMount方法中,并使其正确呈现.如果查看链接的JSFiddle,您将看到<BsPopover />我制作的通用包装器,它会为您处理所有Bootstrap调用,包括在从DOM中删除包装器组件后正确清理弹出组件.