Bootstrap 无法轻松地在弹出框内渲染动态组件。如果您要呈现的弹出框是静态的,您可以简单地使用 React renderComponentToString
,它接受一个组件并通过回调返回一个 HTML 字符串:
var html = React.renderComponentToString(<MusicList />);
$(this.getDOMNode()).popover({
html: true,
content: html
});
但是,如果您的组件具有任何交互性,那么该策略将不起作用,因为 React 永远没有机会附加事件处理程序(或运行任何自定义生命周期方法)。事实上,Bootstrap 没有提供适当的钩子来使您的弹出内容动态化。
也就是说,可以通过修补 Bootstrap 来完成这项工作。我创建了一个具有动态弹出内容的现场演示:
http://jsfiddle.net/spicyj/q6hj7/
请注意,当前时间由每秒更新的 React 组件在弹出框内呈现。
这个弹出框是如何创建的?
我修补了Bootstrap 弹出框的setContent
方法,除了 HTML 或文本字符串外,还采用了 React 组件。我没有使用 jQueryhtml
或text
方法,而是使用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]);
}
};
现在你可以写了
$(this.getDOMNode()).popover({
react: true,
content: <MusicList />
});
在您的componentDidMount
方法中并使其正确呈现。如果您查看链接的 JSFiddle,您会看到我制作的通用<BsPopover />
包装器,它为您处理所有 Bootstrap 调用,包括在从 DOM 中删除包装器组件后正确清理弹出组件。