Question:
如何将反应组件的方法暴露给其他地方?
例如,我想从React之外的元素调用React-Router的this.context.router.push(location) .
也许我可以在窗口对象中添加一个React组件的方法,以便可以从任何通用DOM事件监听器甚至控制台调用它?
Background/Use Case:
我想在我的React应用程序中使用jQuery DataTables,因为它提供了许多插件和配置,这些插件和配置在React生态系统中仍然不可用 .
我从现有的React数据表组件开始(下面的实现) .
原始提供了传递渲染函数的不错选项,例如,渲染单元格内的其他React组件 . 下面,“产品名称”列中的单元格呈现为React-Router <Link />组件 .
const data = [
{
product_id: '5001',
product_price: '$5',
product_name: 'Apple'
},
...
];
const renderUrl =
(val, row) => {
return (<Link to={`/product/${row.product_id}`}>{row.product_name}</Link>);
};
const columns = [
{ title: 'Product Name', prop: 'product_id', render: renderUrl },
{ title: 'Price', prop: 'product_price' },
];
<DataTable
className="datatable-container"
columns={columns}
initialData={data}
/>
我修改现有组件所做的工作涉及将表隐藏在React的DOM diffing算法中,因为当jQuery DataTables修改DOM时它会破坏 .
-
将组件的render()代码移动到类的自定义方法getDtMarkup()中(在反应生命周期之外) .
-
render()现在输出一个带有ref和id的空div
render() {
return (
<div>
<div ref="dtContainer" id="dtContainer"></div>
</div>
);
}
- componentDidMount使用ReactDomServer.renderToStaticMarkup将React组件转换为普通的非反应标记,并将其附加到render()的#dtContainer div中 . 最后,jQuery DataTables将渲染的表html初始化为一个花哨的'jQuery DataTable' .
componentDidMount() {
let table = this.getDTMarkup();
let dtContainer = this.refs.dtContainer;
let renderedTable = ReactDOMServer.renderToStaticMarkup(table, dtContainer);
$('#dtContainer').append(renderedTable);
let jqueryTable = $('#dt'); // hard coded in getDTMarkup() for now
// Turn html table into a jQuery DataTable with desired config options
jqueryTable.DataTable({
dom: '<"html5buttons"B>lTfgitp',
buttons: [
'copy', 'csv', 'excel', 'pdf', 'print'
],
"pagingType": 'numbers',
"bAutoWidth": false,
"bDestroy": true,
"fnDrawCallback": function() {
console.log('datatables fnDrawCallback');
}
});
}
src https://github.com/alecperkey/react-jquery-datatables/blob/master/src/Table.js#L89-L111
我问这个问题的限制是我现在无法在这个静态的非React标记中使用诸如<Link />之类的React组件 . 我现在正在使用<a href =“”>,但这会重新加载页面,这会更慢并导致浏览器的白色闪烁 .
1 回答
有几种方法可以将React组件与“外部应用程序”连接起来
您可以将方法作为道具传递给组件,如:
http://jsbin.com/zujebirusa/1/edit?js,output
使用附加到窗口的全局方法 . 请记住,它很难维护,因为它会污染全局命名空间 .
http://jsbin.com/woyokasano/1/edit?js,output
使用ES6模块系统,以保持您的代码库与单独的范围整洁