如何在React中使用jQuery UI?我已经通过Googling看到了几个示例,但它们似乎都已过时。
如果您 确实 需要这样做,这是我正在使用的一种方法。
计划: 创建一个组件来管理jQuery插件 。该组件将提供以React为中心的jQuery组件视图。此外,它将:
props
让我们探索一个实际的示例,如何使用jQuery UI Sortable插件做到这一点。
如果您只想获取包装好的jQuery UI Sortable示例的最终版本,请执行以下操作:
…此外,以下是 较长的注释 代码段 的缩写 :
class Sortable extends React.Component { componentDidMount() { this.$node = $(this.refs.sortable); this.$node.sortable({ opacity: this.props.opacity, change: (event, ui) => this.props.onChange(event, ui) }); } shouldComponentUpdate() { return false; } componentWillReceiveProps(nextProps) { if (nextProps.enable !== this.props.enable) this.$node.sortable(nextProps.enable ? 'enable' : 'disable'); } renderItems() { return this.props.data.map( (item, i) => <li key={i} className="ui-state-default"> <span className="ui-icon ui-icon-arrowthick-2-n-s"></span> { item } </li> ); } render() { return ( <ul ref="sortable"> { this.renderItems() } </ul> ); } componentWillUnmount() { this.$node.sortable('destroy'); } };
(可选)您可以设置默认道具(在不传递任何道具的情况下)和道具类型:
Sortable.defaultProps = { opacity: 1, enable: true }; Sortable.propTypes = { opacity: React.PropTypes.number, enable: React.PropTypes.bool, onChange: React.PropTypes.func.isRequired };
…以及使用该<Sortable />组件的方法:
<Sortable />
class MyComponent extends React.Component { constructor(props) { super(props); // Use this flag to disable/enable the <Sortable /> this.state = { isEnabled: true }; this.toggleEnableability = this.toggleEnableability.bind(this); } toggleEnableability() { this.setState({ isEnabled: ! this.state.isEnabled }); } handleOnChange(event, ui) { console.log('DOM changed!', event, ui); } render() { const list = ['ReactJS', 'JSX', 'JavaScript', 'jQuery', 'jQuery UI']; return ( <div> <button type="button" onClick={this.toggleEnableability}> Toggle enable/disable </button> <Sortable opacity={0.8} data={list} enable={this.state.isEnabled} onChange={this.handleOnChange} /> </div> ); } } ReactDOM.render(<MyComponent />, document.getElementById('app'));
对于那些想要了解 原因 和 方式的人 。以下是逐步指南:
我们的组件将接受项目(字符串)的数组(列表)作为dataprop。
data
class Sortable extends React.Component { componentDidMount() { // Every React component has a function that exposes the // underlying DOM node that it is wrapping. We can use that // DOM node, pass it to jQuery and initialize the plugin. // You'll find that many jQuery plugins follow this same pattern // and you'll be able to pass the component DOM node to jQuery // and call the plugin function. // Get the DOM node and store the jQuery element reference this.$node = $(this.refs.sortable); // Initialize the jQuery UI functionality you need // in this case, the Sortable: https://jqueryui.com/sortable/ this.$node.sortable(); } // jQuery UI sortable expects a <ul> list with <li>s. renderItems() { return this.props.data.map( (item, i) => <li key={i} className="ui-state-default"> <span className="ui-icon ui-icon-arrowthick-2-n-s"></span> { item } </li> ); } render() { return ( <ul ref="sortable"> { this.renderItems() } </ul> ); } };
假设我们要在排序时配置帮助程序的不透明度。我们将opacity在插件配置中使用该选项,该选项的值从0.01到1。
opacity
0.01
1
class Sortable extends React.Component { // ... omitted for brevity componentDidMount() { this.$node = $(this.refs.sortable); this.$node.sortable({ // Get the incoming `opacity` prop and use it in the plugin configuration opacity: this.props.opacity, }); } // ... omitted for brevity }; // Optional: set the default props, in case none are passed Sortable.defaultProps = { opacity: 1 };
现在,我们可以在代码中使用该组件:
<Sortable opacity={0.8} />
同样,我们可以映射任何jQUery UI Sortable选项。
为了执行一些React逻辑,您很可能需要连接一些插件方法,例如,操纵状态吧。
这样做的方法如下:
class Sortable extends React.Component { // ... omitted for brevity componentDidMount() { this.$node = $(this.refs.sortable); this.$node.sortable({ opacity: this.props.opacity, // Get the incoming onChange function // and invoke it on the Sortable `change` event change: (event, ui) => this.props.onChange(event, ui) }); } // ... omitted for brevity }; // Optional: set the prop types Sortable.propTypes = { onChange: React.PropTypes.func.isRequired };
以及使用方法:
<Sortable opacity={0.8} onChange={ (event, ui) => console.log('DOM changed!', event, ui) } />
在ReactJS在实际DOM中添加元素之后,我们需要将Future控件传递给jQuery。否则,ReactJS将永远不会重新渲染我们的组件,但是我们不想要那样。我们希望jQuery负责所有更新。
React生命周期方法可助您一臂之力!
使用shouldComponentUpdate()可以让React知道组件的输出是否不受当前状态或道具更改的影响。默认行为是在每个状态更改(绝大多数情况下)都重新呈现,但是我们不希望这种行为!
shouldComponentUpdate()当接收到新的道具或状态时,在渲染之前调用。如果shouldComponentUpdate()回报false,然后componentWillUpdate(),render()和componentDidUpdate()将不会被调用。
shouldComponentUpdate()
false
componentWillUpdate()
render()
componentDidUpdate()
然后,我们使用componentWillReceiveProps(),我们与进行比较this.props,nextProps并仅在必要时调用jQuery UI可排序更新。对于此示例,我们将实现jQuery UI Sortable的enable / disable选项。
componentWillReceiveProps()
this.props
nextProps
class Sortable extends React.Component { // Force a single-render of the component, // by returning false from shouldComponentUpdate ReactJS lifecycle hook. // Right after ReactJS adds the element in the actual DOM, // we need to pass the future control to jQuery. // This way, ReactJS will never re-render our component, // and jQuery will be responsible for all updates. shouldComponentUpdate() { return false; } componentWillReceiveProps(nextProps) { // Each time when component receives new props, // we should trigger refresh or perform anything else we need. // For this example, we'll update only the enable/disable option, // as soon as we receive a different value for this.props.enable if (nextProps.enable !== this.props.enable) { this.$node.sortable(nextProps.enable ? 'enable' : 'disable'); } } // ... omitted for brevity }; // Optional: set the default props, in case none are passed Sortable.defaultProps = { enable: true }; // Optional: set the prop types Sortable.propTypes = { enable: React.PropTypes.bool };
许多jQuery插件提供了一种在不再需要时自行清理的机制。jQuery UI Sortable提供了一个事件,我们可以触发该事件来告诉插件取消绑定其DOM事件并销毁。React生命周期方法再次为您提供了帮助,并提供了一种机制,可以在卸载组件时挂入。
class Sortable extends React.Component { // ... omitted for brevity componentWillUnmount() { // Clean up the mess when the component unmounts this.$node.sortable('destroy'); } // ... omitted for brevity };
用React包装jQuery插件并非总是最佳选择。但是,很高兴知道它是一个选项以及如何实现解决方案。如果要将旧版jQuery应用程序迁移到React,或者只是找不到适合您情况的React插件,这是一个可行的选择。
在库修改DOM的情况下,我们尝试使React远离它 。当它完全控制DOM时,React效果最佳。在这些情况下,React组件更多地是第三方库的包装器。通常,通过使用componentDidMount / componentWillUnmount来初始化/销毁第三方库。和props作为一种方式,为父母提供了一种方式来定制孩子包装的第三方库的行为并与插件事件挂钩。
您可以使用这种方法来集成几乎所有jQuery插件 !