
Créez des composants agnostiques de cadre qui sont vraiment réutilisables et interopérables avec tous les avantages de l'écosystème React - en utilisant l'API HTML5 Custom Elements pour étendre le vocabulaire de HTML.
npm install react-standalone --save Jetez un œil au composant mars-weather pour une idée sur la façon de structurer votre composant réutilisable - mais essentiellement un composant consiste en un nom de balise - comme mars-weather , le component React et un schéma facultatif à l'aide osom .
import { createModule } from 'standalone' ;
import schema from './schema' ;
import component from './component' ;
export default createModule ( 'mars-weather' , { schema , component } ) ; Une fois que vous aurez créé votre package, un élément personnalisé sera créé avec le tagName fourni qui peut être intégré dans le DOM - toutes les méthodes de cycle de vie React seront invoquées, telles que componentWillUnmount lorsque l'élément aura été supprimé du DOM.
< mars-weather /> Comme le composant mars-weather est un élément entièrement personnalisé, il peut être intégré dans n'importe quel cadre JavaScript - Angular, Vue, React, Cycle, Ember, Vanilla, etc ...
Bonus: Utilisez Keo avec des limites d'ombre pour une vraie sensation de polymère.
En spécifiant les attributs sur l'élément personnalisé, les valeurs des attributs sont transmises dans votre composant en tant qu'accessoires - toutes les modifications apportées à l' state seront gérées en interne à votre composant, tandis que toute modification des attributs de votre élément provoquera une retenue avec les props mis à jour.
Dans l'exemple de mars-weather , nous avons configuré la méthode getDefaultProps pour renvoyer les accessoires par défaut, mais les utilisateurs peuvent remplacer l'hélice unit en transmettant un attribut data nommé data-unit .
< mars-weather data-unit =" C " /> Dans le cas ci-dessus, l'attribut de data-unit sera transformé en unit - à mesure que Standalone supprime les data- préfixes - puis redevient votre composant, vous permettant d'accéder à l'attribut comme this.props.unit .
Comme tous les attributs HTML sont string S, Standalone vous permet de spécifier un schéma pour votre composant, qui transformera les attributs string en type de données que vous attendez en utilisant osom .
export default {
unit : {
type : String ,
default : 'F'
}
} ; Une fois que vous avez configuré le schéma à utiliser pour votre composant, vous pouvez heureusement configurer les propTypes React habituels en spécifiant le type de données que vous attendez de passer.
En utilisant des événements personnalisés, vous pouvez facilement configurer un canal de communication entre vos composants et le monde extérieur.
// Instantiate `CustomEvent` and then specify the name of the event, followed
// by the payload which will be passed to your listener function.
const event = new CustomEvent ( 'migrate-planets' , {
bubbles : true ,
detail : {
planet : 'Saturn'
}
} ) ;
findDOMNode ( this ) . dispatchEvent ( event ) ; Il est crucial que vous émettez l'événement en tant que bubbles: true sinon l'événement s'arrêterait simplement au nœud findDOMNode(this) plutôt que de bouillonner jusqu'au nœud mars-weather - à moins que vous ne disposiez l'événement sur le nœud mars-weather en utilisant findDOMNode(this).parentNode .
Dans votre composant, vous émettez l'événement - CustomEvent - en utilisant dispatchEvent , puis liez votre élément personnalisé - tel que mars-weather - en utilisant addEventListener de l'extérieur.
const node = document . querySelector ( 'mars-weather' ) ;
node . addEventListener ( 'migrate-planets' , event => {
// Update the `data-planet` attribute to reflect the newly migrated planet
// which will cause the component to re-render with the update prop.
node . setAttribute ( 'data-planet' , event . detail . planet ) ;
} ) ; Comme invoquer setAttribute sur votre composant provoque réagir pour réagir votre composant, il peut être utile de fournir une charge utile JSON à votre composant à la place - surtout si vous définissez une multitude d'attributs; Cela aide également aux performances car vous n'auriez besoin que d'un seul setAttribute pour mettre à jour de nombreux accessoires et renvoyer.
En définissant un schéma, vous pouvez spécifier un attribut qui sera analysé en JSON.
export default {
payload : {
type : JSON . parse
}
} La connexion d'une chaîne JSON à l'attribut data-payload de votre élément le fera analyser un objet à l'aide de JSON.parse , et transmis à votre composant React en tant this.props.payload qui peut être défini dans les propTypes à l'aide PropTypes.shape .
Tous les composants Standalone étendent HTMLElement.prototype et permettent d'ajouter des fonctions personnalisées à l'élément - que vous pouvez invoquer une fois que vous avez une référence à l'élément associé. Jetez un œil aux méthodes de mars-weather pour un exemple.
const getWeather = function ( ) {
const weather = this . component . state . weather . atmoOpacity . toLowerCase ( ) ;
return `The current weather on Mars is ${ weather } !` ;
} ;
// ...
document . querySelector ( 'mars-weather' ) . getWeather ( ) ; Lorsqu'un composant a été annexé au DOM, il mettra à jour son prototype HTMLElement pour attribuer le composant rendu à getPrototypeOf(this).component - Cela vous permet commodément d'accéder aux props et state , et à invoquer les fonctions internes au composant React.
Il convient de noter que this.component ne sera disponible qu'une fois le composant annexé au DOM.
Avec l'API des éléments personnalisés, il est possible d'étendre les éléments existants - en utilisant l'attribut is pour spécialiser. Standalone vous permet d'étendre les éléments en passant l'élément à s'étendre.
// Creates a `mars-weather` element.
export default createModule ( 'mars-weather' , { schema , methods , component } ) ;
// Creates a `input[is="mars-weather"]` element.
export default createModule ( 'input/mars-weather' , { schema , methods , component } ) ; Il convient de noter que lorsque vous étendez un élément connu, votre élément étendra son prototype - dans le cas au-dessus de l'élément mars-weather étendra input et son prototype HTMLInputElement .
* Nécessite l'excellent webcomponents-lite.js polyfill (13k gzipip)