小编典典

如何在React JS中使用jQuery UI

reactjs

如何在React中使用jQuery UI?我已经通过Googling看到了几个示例,但它们似乎都已过时。


阅读 364

收藏
2020-07-22

共1个答案

小编典典

如果您 确实 需要这样做,这是我正在使用的一种方法。

计划: 创建一个组件来管理jQuery插件 。该组件将提供以React为中心的jQuery组件视图。此外,它将:

  • 使用React生命周期方法来初始化和拆除jQuery插件;
  • 使用React props作为插件配置选项并连接到插件的方法事件;
  • 卸载组件时销毁插件。

让我们探索一个实际的示例,如何使用jQuery UI
Sortable
插件做到这一点。


TLDR:最终版本

如果您只想获取包装好的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 />组件的方法:

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'));

完整说明

对于那些想要了解 原因方式的人 。以下是逐步指南:

步骤1:创建一个组件。

我们的组件将接受项目(字符串)的数组(列表)作为dataprop。

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>
        );
    }
};

步骤2:通过道具传递配置选项

假设我们要在排序时配置帮助程序的不透明度。我们将opacity在插件配置中使用该选项,该选项的值从0.011

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选项

步骤3:插件事件的连接函数。

为了执行一些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) } />

步骤4:将未来的更新控件传递给jQuery

在ReactJS在实际DOM中添加元素之后,我们需要将Future控件传递给jQuery。否则,ReactJS将永远不会重新渲染我们的组件,但是我们不想要那样。我们希望jQuery负责所有更新。

React生命周期方法可助您一臂之力!

使用shouldComponentUpdate()可以让React知道组件的输出是否不受当前状态或道具更改的影响。默认行为是在每个状态更改(绝大多数情况下)都重新呈现,但是我们不希望这种行为!

shouldComponentUpdate()当接收到新的道具或状态时,在渲染之前调用。如果shouldComponentUpdate()回报false,然后componentWillUpdate()render()componentDidUpdate()将不会被调用。

然后,我们使用componentWillReceiveProps(),我们与进行比较this.propsnextProps并仅在必要时调用jQuery
UI可排序更新。对于此示例,我们将实现jQuery UI Sortable的enable / disable选项。

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
};

步骤5:清理混乱。

许多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插件

2020-07-22