Composants inspirés de la lame Laravel pour posthtml
npm i -D posthtml-componentCe plugin PosthTML fournit une syntaxe HTML pour l'utilisation de composants dans vos modèles HTML. Si vous connaissez Blade, React, Vue ou similaire, vous trouverez que la syntaxe est familière, car ce plugin s'inspire d'eux.
Voir également le premier UI Bootstrap PosthTML à l'aide de ce plugin et vérifiez également le modèle de démarrage ici.
| Nom | Taper | Défaut | Description |
|---|---|---|---|
| racine | String | './' | Chemin racinaire où chercher des composants. |
| dossiers | String[] | [''] | Tableau de chemins par rapport aux options.root . |
| fichier extension | String|String[] | 'html' | Extensions de fichiers de composant à rechercher. |
| tagPrefix | String | 'x-' | Préfixe de balise. |
| étiqueter | String|Boolean | false | Tag de composant. Utiliser avec options.attribute . Booléen uniquement false . |
| attribut | String | 'src' | Attribut à utiliser pour définir le fichier de chemin vers le composant. |
| espaces de noms | String[] | [] | Tableau de chemins racine d'espace de noms, de chemins de secours et de chemins de remplacement personnalisés. |
| département d'espace | String | '::' | Séparateur de l'espace de noms pour les noms de balises. |
| rendement | String | 'yield' | Nom de balise pour injecter le contenu des composants principaux. |
| fente | String | 'slot' | Nom de la balise pour les machines à sous |
| remplir | String | 'fill' | Nom de la balise pour remplir les emplacements. |
| slotseparator | String | ':' | Nom Séparateur pour les balises <slot> et <fill> . |
| empiler | String | 'stack' | Nom de la balise pour <stack> . |
| pousser | String | 'push' | Nom de la balise pour <push> . |
| PropSScriptAttribute | String | 'props' | Attribut dans <script props> pour récupérer les accessoires de composants. |
| propscontext | String | 'props' | Nom de l'objet à l'intérieur du script pour le traitement des accessoires. |
| propsattribut | String | 'props' | Nom d'attribut pour définir les accessoires comme JSON sur une balise composante. |
| accessoire | String | 'props' | Utilisé pour récupérer les accessoires transmis à l'emplacement via $slots.slotName.props . |
| parserroptions | Object | {recognizeSelfClosing: true} | Passer des options à posthtml-parser . |
| expressions | Object | {} | Passer des options aux posthtml-expressions . |
| plugins | Array | [] | Plugins PosthTML pour s'appliquer à chaque composant analysé. |
| correspondant | Object | [{tag: options.tagPrefix}] | Tableau d'objets utilisés pour faire correspondre les balises. |
| servale | Object | {} | Règles supplémentaires pour le plugin d'analyse des attributs. |
| strict | Boolean | true | Basculez l'exception de lancer. |
| MergeCustomzer | Function | function | Rappel pour Lodash mergeWith pour fusionner options.expressions.locals and accessoires. |
| services publics | Object | {merge: _.mergeWith, template: _.template} | Méthodes d'utilité transmises à <script props> . |
| ElementAttributes | Object | {} | Objet avec noms de balises et modificateurs de fonction de valid-attributes.js . |
| Safelistattributes | String[] | ['data-*'] | Tableau de noms d'attribut à ajouter aux attributs valides par défaut. |
| blockListAttributes | String[] | [] | Tableau de noms d'attribut à supprimer des attributs valides par défaut. |
Créez le composant:
<!-- src/button.html -->
< button type =" button " class =" btn " >
< yield > </ yield >
</ button >Utilisez-le:
<!-- src/index.html -->
< html >
< body >
< x-button type =" submit " class =" btn-primary " > Submit </ x-button >
</ body >
</ html >Init posthtml:
// index.js
const posthtml = require ( 'posthtml' )
const components = require ( 'posthtml-component' )
const { readFileSync , writeFileSync } = require ( 'node:fs' )
posthtml ( [
components ( { root : './src' } )
] )
. process ( readFileSync ( 'src/index.html' , 'utf8' ) )
. then ( result => writeFileSync ( 'dist/index.html' , result . html , 'utf8' ) )Résultat:
<!-- dist/index.html -->
< html >
< body >
< button type =" submit " class =" btn btn-primary " > Submit </ button >
</ body >
</ html > Vous avez peut-être remarqué que le composant src/button.html contient des attributs type et class , et que nous avons également passé ces attributs lorsque nous l'avons utilisé dans src/index.html .
Le résultat est que type a été remplacé et class a été fusionnée.
Par défaut, les attributs class et style sont fusionnés, tandis que tous les autres attributs sont remplacés. Vous pouvez également remplacer les attributs class et style en override: à l'attribut de classe.
Par exemple:
< x-button override:class =" btn-custom " > Submit </ x-button >
<!-- Output -->
< button type =" button " class =" btn-custom " > Submit </ button > Tous les attributs que vous transmettez au composant seront ajoutés au premier nœud de votre composant ou au nœud avec un attribut nommé attributes , uniquement s'ils ne sont pas définis comme props via <script props> ou s'ils ne sont pas des "attributs connus" (voir valide-attributes.js).
Vous pouvez également définir les attributs considérés comme valides, via les options du plugin.
Plus de détails à ce sujet dans la section Attributs.
La balise <yield> est l'endroit où le contenu que vous transmettez à un composant sera injecté.
Le plugin configure l'analyseur PosthTML pour reconnaître les balises d'auto-fermeture, vous pouvez donc également écrire comme <yield /> .
Pour Brevity, nous utiliserons des balises d'auto-fermeture dans les exemples.
Par défaut, le plugin recherche des composants avec l'extension .html . Vous pouvez modifier cela en passant un tableau d'extensions à l'option fileExtension .
Lorsque vous utilisez un tableau, si deux fichiers avec le même nom correspondent aux deux extensions, le fichier correspondant à la première extension du tableau sera utilisé.
const posthtml = require ( 'posthtml' )
const components = require ( 'posthtml-component' )
posthtml ( [
components ( {
root : './src' , // contains layout.html and layout.md
fileExtension : [ 'html' , 'md' ]
} )
] )
. process ( `<x-layout />` )
. then ( result => console . log ( result . html ) ) // layout.html content Voir également le dossier docs-src où vous pouvez trouver plus d'exemples.
Vous pouvez cloner ce dépôt et exécuter npm run build pour les compiler.
Vous pouvez utiliser les composants de plusieurs manières, ou également une combinaison d'entre eux.
Si vous souhaitez utiliser des composants comme «inclut», vous pouvez définir les noms d'attributs TAG et src .
En utilisant notre exemple de composant de bouton précédent, nous pouvons définir les noms de balise et d'attribut, puis l'utiliser comme ceci:
Init posthtml:
// index.js
require ( 'posthtml' ) (
require ( 'posthtml-component' ) ( {
root : './src' ,
tag : 'component' ,
attribute : 'src'
} ) )
. process ( /* ... */ )
. then ( /* ... */ ) Si vous avez besoin de plus de contrôle sur la correspondance de balises, vous pouvez passer un tableau de correspondant ou d'objet unique via options.matcher :
// index.js
const options = {
root : './src' ,
matcher : [
{ tag : 'a-tag' } ,
{ tag : 'another-one' } ,
{ tag : new RegExp ( `^app-` , 'i' ) } ,
]
} ;
require ( 'posthtml' ) ( require ( 'posthtml-component' ) ( options ) )
. process ( /* ... */ )
. then ( /* ... */ ) Avec posthtml-components vous n'avez pas besoin de spécifier le nom du chemin lorsque vous utilisez la syntaxe x-tag-name .
Configuration PosthTML:
// index.js
const options = {
root : './src' ,
tagPrefix : 'x-'
} ;
require ( 'posthtml' ) ( require ( 'posthtml-component' ) ( options ) )
. process ( /* ... */ )
. then ( /* ... */ )Utiliser:
<!-- src/index.html -->
< html >
< body >
< x-button > Submit </ x-button >
</ body >
</ html > Si vos composants sont dans un sous-dossier, vous pouvez utiliser dot pour y accéder:
<!-- src/components/forms/button.html -->
< x-forms .button > Submit </ x-forms .button > Si vos composants sont dans un sous-dossier avec plusieurs fichiers, afin d'éviter d'écrire le nom du fichier principal, vous pouvez utiliser index.html sans le spécifier.
Voici un exemple:
<!-- src/components/modals/index.html -->
< x-modal .index > Submit </ x-modal .index >
<!-- You may omit "index" part since the file is named "index.html" -->
< x-modal > Submit </ x-modal > Vous pouvez transmettre des options à posthtml-parser via options.parserOptions .
// index.js
const options = {
root : './src' ,
parserOptions : { decodeEntities : true }
} ;
require ( 'posthtml' ) ( require ( 'posthtml-component' ) ( options ) )
. process ( 'some HTML' , options . parserOptions )
. then ( /* ... */ ) Important
Les parserOptions que vous transmettez au plugin doivent également être transmises dans la méthode process dans votre code, sinon votre build PosthTML utilisera des défauts de défaut posthtml-parser et remplacera tout ce que vous avez transmis à posthtml-component .
Le plugin prend en charge les balises d'auto-fermeture par défaut, mais vous devez vous assurer de les activer également dans la méthode process dans votre code, en passant recognizeSelfClosing: true dans l'objet Options:
// index.js
require ( 'posthtml' ) ( require ( 'posthtml-component' ) ( { root : './src' } ) )
. process ( 'your HTML...' , { recognizeSelfClosing : true } )
. then ( /* ... */ ) Si vous ne ajoutez pas cela au process , PosthTML utilisera les défauts de défaut posthtml-parser et ne prendra pas en charge les balises de composants auto-fermes. Cela se traduira par tout après qu'une étiquette d'auto-ferme n'étant pas sortie.
Vous avez un contrôle total sur l'endroit où vos fichiers de composants existent. Une fois que vous avez défini le chemin racine de base de vos composants, vous pouvez ensuite définir plusieurs dossiers.
Par exemple, si votre racine est ./src et que vous avez plusieurs dossiers où vous avez vos composants, par exemple ./src/components et ./src/layouts , vous pouvez configurer le plugin comme ci-dessous:
// index.js
const options = {
root : './src' ,
folders : [ 'components' , 'layouts' ]
} ;
require ( 'posthtml' ) ( require ( 'posthtml-component' ) ( options ) )
. process ( /* ... */ )
. then ( /* ... */ )Avec les espaces de noms, vous pouvez définir un chemin racine de niveau supérieur vers vos composants.
Il peut être utile pour gérer les thèmes personnalisés, où vous définissez une racine de niveau supérieur spécifique avec une racine de secours pour le moment où un composant n'est pas trouvé, et une racine personnalisée pour le remplacement.
Cela permet de créer des structures de dossiers comme celle-ci:
src (dossier racine)components (dossier pour des composants comme modal, bouton, etc.)layouts (dossier pour les composants de mise en page comme la disposition de la base, l'en-tête, le pied de page, etc.)theme-dark (dossier d'espace de noms pour le thème-sark)components (dossier pour les composants pour le thème sombre)layouts (dossier pour les composants de mise en page pour le thème sombre)theme-light (dossier d'espace de noms pour la lumière de thème)components (dossier pour les composants pour le thème léger)layouts (dossier pour les composants de mise en page pour le thème sombre)custom (dossier personnalisé pour remplacer vos thèmes d'espace de noms)theme-dark (dossier personnalisé pour le thème sombre de remplacer)components (dossier pour les composants de remplacement du thème sombre)layouts (dossier pour les composants de mise en page de remplacement du thème sombre)theme-light (dossier personnalisé pour le thème Light Override)components (dossier pour les composants de remplacement du thème sombre)layouts (dossier pour les composants de mise en page de remplacement du thème sombre)Et les options seraient comme:
// index.js
const options = {
// Root for component without namespace
root : './src' ,
// Folders is always appended in 'root' or any defined namespace's folders (base, fallback or custom)
folders : [ 'components' , 'layouts' ] ,
namespaces : [ {
// Namespace name will be prepended to tag name (example <x-theme-dark::button>)
name : 'theme-dark' ,
// Root of the namespace
root : './src/theme-dark' ,
// Fallback root when a component is not found in namespace
fallback : './src' ,
// Custom root for overriding, the lookup happens here first
custom : './src/custom/theme-dark'
} , {
// Light theme
name : 'theme-light' ,
root : './src/theme-light' ,
fallback : './src' ,
custom : './src/custom/theme-light'
} , {
/* ... */
} ]
} ;Utilisez l'espace de noms du composant:
<!-- src/index.html -->
< html >
< body >
< x-theme-dark : :button >Submit</ theme-dark : :button >
< x-theme-light : :button >Submit</ theme-light : :button >
</ body >
</ html >Les composants peuvent définir des créneaux qui peuvent être remplis de contenu lorsqu'ils sont utilisés.
Par exemple:
<!-- src/modal.html -->
< div class = " modal " >
< div class = " modal-header " >
< slot : header />
</ div >
< div class = " modal-body " >
< slot : body />
</ div >
< div class = " modal-footer " >
< slot : footer />
</ div >
</ div >Utilisez le composant:
<!-- src/index.html -->
< x-modal >
< fill : header >Header content</ fill : header >
< fill : body >Body content</ fill : body >
< fill : footer >Footer content</ fill : footer >
</ x-modal >Résultat:
<!-- dist/index.html -->
< div class =" modal " >
< div class =" modal-header " >
Header content
</ div >
< div class =" modal-body " >
Body content
</ div >
< div class =" modal-footer " >
Footer content
</ div >
</ div >Par défaut, le contenu de l'emplacement est remplacé, mais vous pouvez également annexer ou ajouter le contenu, ou conserver le contenu par défaut en ne remplissant pas la fente.
Ajoutez un contenu par défaut dans le composant:
<!-- src/modal.html -->
< div class = " modal " >
< div class = " modal-header " >
< slot : header >Default header</ slot : header >
</ div >
< div class = " modal-body " >
< slot : body >content</ slot : body >
</ div >
< div class = " modal-footer " >
< slot : footer >Footer</ slot : footer >
</ div >
</ div > <!-- src/index.html -->
< x-modal >
< fill : body prepend>Prepend body</ fill : body >
< fill : footer append>content</ fill : footer >
</ x-modal >Résultat:
<!-- dist/index.html -->
< div class =" modal " >
< div class =" modal-header " >
Default header
</ div >
< div class =" modal-body " >
Prepend body content
</ div >
< div class =" modal-footer " >
Footer content
</ div >
</ div >Vous pouvez pousser du contenu vers des piles nommées qui peuvent être rendues ailleurs, comme dans un autre composant. Cela peut être particulièrement utile pour spécifier tout JavaScript ou CSS requis par vos composants.
Tout d'abord, ajoutez une balise <stack> à votre HTML:
<!-- src/index.html -->
<html>
<head>
+ <stack name="styles" />
</head>
<body>
<x-modal>
<fill:header>Header content</fill:header>
<fill:body>Body content</fill:body>
<fill:footer>Footer content</fill:footer>
</x-modal>
+ <stack name="scripts" />
</body>
</html>Ensuite, dans les composants modaux ou tout autre composant enfant, vous pouvez pousser le contenu vers cette pile:
<!-- src/modal.html -->
< div class = " modal " >
< div class = " modal-header " >
< slot : header />
</ div >
< div class = " modal-body " >
< slot : body />
</ div >
< div class = " modal-footer " >
< slot : footer />
</ div >
</ div >
< push name = " styles " >
< link href = " https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css " rel = " stylesheet " >
</ push >
< push name = " scripts " >
< script src = " https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js " ></ script >
</ push >La sortie sera:
<!-- dist/index.html -->
< html >
< head >
< link href =" https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css " rel =" stylesheet " >
</ head >
< body >
< div class =" modal " >
< div class =" modal-header " >
Header content
</ div >
< div class =" modal-body " >
Body content
</ div >
< div class =" modal-footer " >
Footer content
</ div >
</ div >
< script src =" https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js " > </ script >
</ body >
</ html > L'attribut once vous permet de pousser du contenu une seule fois par cycle de rendu.
Par exemple, si vous rendez un composant donné dans une boucle, vous ne souhaiterez peut-être pousser que JavaScript et CSS la première fois que le composant est rendu.
Exemple.
<!-- src/modal.html -->
< div class =" modal " >
<!-- ... -->
</ div >
<!-- The push content will be pushed only once in the stack -->
< push name =" styles " once >
< link href =" https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css " rel =" stylesheet " >
</ push >
< push name =" scripts " once >
< script src =" https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js " > </ script >
</ push > Par défaut, le contenu est poussé dans la pile dans l'ordre donné. Si vous souhaitez constituer du contenu au début d'une pile, vous pouvez utiliser l'attribut prepend :
< push name =" scripts " >
<!-- This will be second -->
< script src =" /example.js " > </ script >
</ push >
<!-- Later... -->
< push name =" scripts " prepend >
<!-- This will be first -->
< script src =" /example-2.js " > </ script >
</ push > props peuvent être transmis aux composants dans les attributs HTML. Pour les utiliser dans un composant, ils doivent être définis dans la balise <script props> du composant.
Par exemple:
<!-- src/alert.html -->
< script props >
module . exports = {
title : props . title || 'Default title'
}
</ script >
< div >
{{ title }}
</ div >Utiliser:
< x-alert title =" Hello world! " />La sortie sera:
< div >
Hello world!
</ div > Si aucun attribut title n'est transmis au composant, la valeur par défaut sera utilisée.
< x-my-alert />La sortie sera:
< div >
Default title
</ div > À l'intérieur <script props> Vous avez accès à des accessoires passés via un objet nommé props .
Voici un exemple de ce que vous pouvez en faire:
<!-- src/modal.html -->
< script props >
module . exports = {
title : props . title || 'Default title' ,
size : props . size ? `modal- ${ props . size } ` : '' ,
items : Array . isArray ( props . items ) ? props . items . concat ( [ 'first' , 'second' ] ) : [ 'first' , 'second' ]
}
</ script >
< div class =" modal {{ size }} " >
< div class =" modal-header " >
{{ title }}
</ div >
< div class =" modal-body " >
< each loop =" item in items " > < span > {{ item }} </ span > </ each >
</ div >
</ div >Utiliser:
< x-modal
size =" xl "
title =" My modal title "
items =' ["third", "fourth"] '
class =" modal-custom "
/>La sortie sera:
< div class =" modal modal-custom modal-xl " >
< div class =" modal-header " >
My modal title
</ div >
< div class =" modal-body " >
< span > first </ span >
< span > second </ span >
< span > third </ span >
< span > fourth </ span >
</ div >
</ div > Remarquez comment l'attribut class que nous avons transmis au composant est fusionné avec la valeur d'attribut de class du premier nœud à l'intérieur.
Vous pouvez modifier la façon dont les attributs sont fusionnés avec des accessoires globaux définis via des options, en passant une fonction de rappel.
Par défaut, tous les accessoires sont étendus dans le composant et ne sont pas disponibles pour les composants imbriqués. Vous pouvez cependant changer cela en conséquence à votre besoin.
Créer un composant:
<!-- src/child.html -->
< script props >
module . exports = {
title : props . title || 'Default title'
}
</ script >
< div >
Prop in child: {{ title }}
</ div > Créez un composant <x-parent> qui utilise <x-child> :
<!-- src/parent.html -->
< script props >
module . exports = {
title : props . title || 'Default title'
}
</ script >
< div >
Prop in parent: {{ title }}
< x-child />
</ div >Utilisez-le:
< x-parent title =" My title " />La sortie sera:
< div >
Prop in parent: My title
< div >
Prop in child: Default title
</ div >
</ div > Comme vous pouvez le voir, title dans le composant <x-child> rend la valeur par défaut et non celle définie via <x-parent> .
Pour changer cela, nous devons aware: le nom d'attribut afin de passer les accessoires aux composants imbriqués.
< x-parent aware:title =" My title " />La sortie sera maintenant:
< div >
Prop in parent: My title
< div >
Prop in child: My title
</ div >
</ div > Vous pouvez transmettre tous les attributs à vos composants et ils seront ajoutés au premier nœud de votre composant, ou au nœud avec un attribut nommé attributes .
Si vous connaissez Vue.js, c'est la même chose que l'attribut soi-disant FallThrough. Ou, avec Laravel Blade, il est d'attributs des composants.
Par défaut, class et style sont fusionnés avec l'attribut class et style existant. Tous les autres attributs sont remplacés par défaut.
Si vous transmettez un attribut défini comme un prop , il ne sera pas ajouté au nœud du composant.
Voici un exemple:
<!-- src/button.html -->
< script props >
module . exports = {
label : props . label || 'A button'
}
</ script >
< button type =" button " class =" btn " >
{{ label }}
</ button >Utilisez le composant:
<!-- src/index.html -->
< x-button type =" submit " class =" btn-primary " label =" My button " />Résultat:
<!-- dist/index.html -->
< button type =" submit " class =" btn btn-primary " > My button </ button > Si vous avez besoin de remplacer les valeurs d'attribut class et style (au lieu de les fusionner), il suffit de dépasser override: au nom d'attribut:
<!-- src/index.html -->
< x-button type =" submit " override:class =" btn-custom " label =" My button " />Résultat:
<!-- dist/index.html -->
< button type =" submit " class =" btn-custom " > My button </ button > Si vous souhaitez que les attributs soient transmis à un certain nœud, utilisez l'attribut attributes :
<!-- src/my-component.html -->
< div class =" first-node " >
< div class =" second-node " attributes >
Hello world!
</ div >
</ div >Utilisez le composant:
<!-- src/index.html -->
< x-my-component class =" my-class " />Résultat:
<!-- dist/index.html -->
< div class =" first-node " >
< div class =" second-node my-class " >
Hello world!
</ div >
</ div >Vous pouvez ajouter des règles personnalisées pour définir la façon dont les attributs sont analysés - nous utilisons PosthTML-ATTRS-PARSER pour les gérer.
Si les configurations par défaut pour les attributs valides ne vous conviennent pas, vous pouvez les configurer comme expliqué ci-dessous.
// index.js
const { readFileSync , writeFileSync } = require ( 'fs' )
const posthtml = require ( 'posthtml' )
const components = require ( 'posthtml-component' )
const options = {
root : './src' ,
// Add attributes to specific tag or override defaults
elementAttributes : {
DIV : ( defaultAttributes ) => {
/* Add new one */
defaultAttributes . push ( 'custom-attribute-name' ) ;
return defaultAttributes ;
} ,
DIV : ( defaultAttributes ) => {
/* Override all */
defaultAttributes = [ 'custom-attribute-name' , 'another-one' ] ;
return defaultAttributes ;
} ,
} ,
// Add attributes to all tags, use '*' as wildcard for attribute name that starts with
safelistAttributes : [
'custom-attribute-name' ,
'attribute-name-start-with-*'
] ,
// Remove attributes from all tags that support it
blocklistAttributes : [
'role'
]
}
posthtml ( components ( options ) )
. process ( readFileSync ( 'src/index.html' , 'utf8' ) )
. then ( result => writeFileSync ( 'dist/index.html' , result . html , 'utf8' ) ) Vous pouvez travailler avec <slot> et <fill> ou vous pouvez créer un composant pour chaque bloc de votre composant, et vous pouvez également les prendre en charge les deux.
Vous pouvez en trouver un exemple à l'intérieur docs-src/components/modal . Voici une courte explication des deux approches.
Supposons que nous voulons créer un composant pour Bootstrap Modal.
Le code requis est:
<!-- Modal HTML -->
< div class =" modal fade " id =" exampleModal " tabindex =" -1 " aria-labelledby =" exampleModalLabel " aria-hidden =" true " >
< div class =" modal-dialog " >
< div class =" modal-content " >
< div class =" modal-header " >
< h1 class =" modal-title fs-5 " id =" exampleModalLabel " > Modal title </ h1 >
< button type =" button " class =" btn-close " data-bs-dismiss =" modal " aria-label =" Close " > </ button >
</ div >
< div class =" modal-body " >
...
</ div >
< div class =" modal-footer " >
< button type =" button " class =" btn btn-secondary " data-bs-dismiss =" modal " > Close </ button >
< button type =" button " class =" btn btn-primary " > Save changes </ button >
</ div >
</ div >
</ div >
</ div >Il y a presque trois blocs de code: l'en-tête, le corps et le pied de page.
Nous pourrions donc créer un composant avec trois emplacements:
<!-- Modal component -->
<div class="modal fade" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
- <h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
+ <slot:header />
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
+ <slot:body />
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
+ <slot:footer />
- <button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>Nous pouvons ensuite l'utiliser comme ceci:
< x-modal
id =" exampleModal "
aria-labelledby =" exampleModalLabel "
>
< slot:header >
< h5 class =" modal-title " id =" exampleModalLabel " > My modal </ h5 >
</ slot:header >
< slot:body >
Modal body content goes here...
</ slot:body >
< slot:footer close =" false " >
< button type =" button " class =" btn btn-primary " > Confirm </ button >
</ slot:footer >
</ x-modal >Une autre approche consiste à diviser le composant dans des composants plus petits, à passer des attributs à chacun d'eux.
Nous créons donc un composant principal puis trois composants plus petits différents:
<!-- Main modal component -->
< div class =" modal fade " tabindex =" -1 " aria-hidden =" true " >
< div class =" modal-dialog " >
< div class =" modal-content " >
< yield />
</ div >
</ div >
</ div > <!-- Header modal component -->
< div class =" modal-header " >
< yield />
</ div > <!-- Body modal component -->
< div class =" modal-body " >
< yield />
</ div > <!-- Footer modal component -->
< div class =" modal-footer " >
< yield />
</ div >Et puis vous pouvez l'utiliser comme ceci:
< x-modal
id =" exampleModal "
aria-labelledby =" exampleModalLabel "
>
< x-modal .header >
< h5 class =" modal-title " id =" exampleModalLabel " > My modal </ h5 >
</ x-modal .header >
< x-modal .body >
Modal body content goes here...
</ x-modal .body >
< x-modal .footer >
< button type =" button " class =" btn btn-primary " > Confirm </ button >
</ x-modal .footer >
</ x-modal >Comme dit de cette manière, vous pouvez transmettre des attributs à chacun d'eux, sans définir des accessoires.
Vous pouvez également combiner les deux approches, puis les utiliser avec des emplacements ou avec de petits composants:
<!-- Modal -->
< div
class =" modal fade "
tabindex =" -1 "
aria-hidden =" true "
aria-modal =" true "
role =" dialog "
>
< div class =" modal-dialog " >
< div class =" modal-content " >
< if condition =" $slots.header?.filled " >
< x-modal .header >
< slot:header />
</ x-modal .header >
</ if >
< if condition =" $slots.body?.filled " >
< x-modal .body >
< slot:body />
</ x-modal .body >
</ if >
< if condition =" $slots.footer?.filled " >
< x-modal .footer close =" {{ $slots.footer?.props.close }} " >
< slot:footer />
</ x-modal .footer >
</ if >
< yield />
</ div >
</ div > <!-- /.modal-dialog -->
</ div > <!-- /.modal -->Vous pouvez maintenant utiliser votre composant avec des emplacements ou avec de petits composants.
Comme vous le remarquez peut-être, en utilisant des emplacements, vous pouvez déjà utiliser également vos petits composants, et vous pouvez également passer des accessoires via $slots qui ont tous les props passés via l'emplacement, et vérifier si l'emplacement est rempli.
Si vous migrez des modules posthtml-extend et / ou posthtml-modules veuillez suivre les mises à jour ici: Posthtml-Components / Issues / 16.
Voir les directives PosthTML et le guide de contribution.
Merci à tous les contributeurs PosthTML et surtout aux contributeurs de modules posthtml-extend et posthtml-modules , dans le cadre du code est volé inspiré de ces plugins. Un grand merci également à Laravel Blade Template Engine.