Si vous realmente besoin de le faire, voici une approche que j'utilise.
Le plan : Créer un composant pour gérer le plugin jQuery . Ce composant fournira une vue centrée sur React du composant jQuery. De plus, il :
- Utilisez les méthodes du cycle de vie de React pour initialiser et démonter le plugin jQuery ;
- Utiliser React
props
comme options de configuration du plugin et s'accrocher aux événements des méthodes du plugin ;
- Détruit le plugin lorsque le composant se démonte.
Voyons, à l'aide d'un exemple concret, comment procéder avec la fonction jQuery UI Sortable plugin.
TLDR : La version finale
Si vous souhaitez simplement récupérer la version finale de l'exemple de jQuery UI Sortable :
... de plus, ci-dessous se trouve le raccourci des commentaires plus longs extrait de code :
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');
}
};
En option, vous pouvez définir des accessoires par défaut (dans le cas où aucun n'est passé) et les types d'accessoires :
Sortable.defaultProps = {
opacity: 1,
enable: true
};
Sortable.propTypes = {
opacity: React.PropTypes.number,
enable: React.PropTypes.bool,
onChange: React.PropTypes.func.isRequired
};
... et voici comment utiliser l'option <Sortable />
composant :
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'));
L'explication complète
Pour ceux d'entre vous qui veulent comprendre por qué y cómo . Voici un guide étape par étape :
Étape 1 : créer un composant.
Notre composant acceptera un tableau (liste) d'éléments (chaînes de caractères) en tant que data
prop.
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>
);
}
};
Étape 2 : Passer les options de configuration via les props
Disons que nous voulons configurer l'opacité de l'aide pendant le tri . Nous utiliserons le opacity
dans la configuration du plugin, qui prend les valeurs de 0.01
a 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
};
Et voici comment nous pouvons utiliser le composant dans notre code maintenant :
<Sortable opacity={0.8} />
De la même manière, nous pouvons mettre en correspondance n'importe quelle jQUery UI Sortable options .
Étape 3 : Accrocher les fonctions sur les événements du plugin.
Vous aurez très probablement besoin de vous connecter à certaines des méthodes du plugin, afin d'exécuter une certaine logique React, par exemple, manipuler l'état let's day.
Voici comment faire :
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
};
Et voici comment l'utiliser :
<Sortable
opacity={0.8}
onChange={ (event, ui) => console.log('DOM changed!', event, ui) } />
Étape 4 : Passer le contrôle des futures mises à jour à jQuery
Juste après que ReactJS ajoute l'élément dans le DOM actuel, nous devons passer le contrôle futur à jQuery. Sinon, ReactJS ne rendra jamais à nouveau notre composant, mais ce n'est pas ce que nous voulons. Nous voulons que jQuery soit responsable de toutes les mises à jour.
Les méthodes du cycle de vie de React viennent à la rescousse !
Utilisez shouldComponentUpdate() pour faire savoir à React si la sortie d'un composant n'est pas affectée par le changement actuel d'état ou de props. Le comportement par défaut est de refaire le rendu à chaque changement d'état, et dans la grande majorité, mais nous ne voulons pas ce comportement !
shouldComponentUpdate()
est invoqué avant le rendu lorsque de nouveaux accessoires ou états sont reçus. Si shouldComponentUpdate()
renvoie à false
entonces componentWillUpdate()
, render()
y componentDidUpdate()
ne sera pas invoquée.
Ensuite, nous utilisons componentWillReceiveProps()
nous comparons this.props
con nextProps
et appeler les mises à jour de jQuery UI Sortable uniquement lorsque cela est nécessaire. Pour cet exemple, nous allons implémenter l'option d'activation/désactivation du jQuery UI Sortable.
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
};
Étape 5 : Nettoyez le désordre.
De nombreux plugins jQuery fournissent un mécanisme pour faire le ménage lorsqu'ils ne sont plus nécessaires. jQuery UI Sortable fournit un événement que nous pouvons déclencher pour dire au plugin de délier ses événements DOM et de se détruire. Les méthodes de cycle de vie de React viennent à nouveau à la rescousse et fournissent un mécanisme à utiliser lorsque le composant est démonté.
class Sortable extends React.Component {
// ... omitted for brevity
componentWillUnmount() {
// Clean up the mess when the component unmounts
this.$node.sortable('destroy');
}
// ... omitted for brevity
};
Conclusion
Envelopper les plugins jQuery avec React n'est pas toujours le meilleur choix. Cependant, il est bon de savoir que c'est une option et comment vous pouvez mettre en œuvre une solution. C'est une option viable si vous migrez une application jQuery héritée vers React ou peut-être que vous ne pouvez tout simplement pas trouver un plugin React qui convient à vos besoins dans votre cas.
Dans le cas où une bibliothèque modifie le DOM, nous essayons de garder React en dehors de son chemin. . React fonctionne mieux lorsqu'il a le contrôle total du DOM. Dans ces cas, les composants React sont plus des enveloppes pour les bibliothèques tierces. La plupart du temps en utilisant le componentDidMount/componentWillUnmount pour initialiser/détruire la bibliothèque tierce. Et les props comme un moyen de donner au parent un moyen de personnaliser le comportement de la bibliothèque tierce que l'enfant enveloppe et de se connecter aux événements du plugin.
Vous pouvez utiliser cette approche pour intégrer presque tous les plugins jQuery. !
2 votes
Oui, je dois le faire. Pour un projet, je dois utiliser beaucoup de composants de jquery ui.
1 votes
Parce que je dois aussi gérer un grand nombre d'États ? @azium