pt —— Fusion des props de transmission
Un composant compte plusieurs éléments internes (le <button> d’un bouton et le <span> qu’il contient, le <input> d’un champ et son icône de préfixe <i>) ; comment l’utilisateur peut-il, depuis l’extérieur, ajuster finement l’un d’entre eux ? La réponse de lh-ui est le paquet de props PT (PassThrough) : le composant expose la prop pt et transmet class / style / attrs séparément, par nom d’élément interne. mergePt se charge de la fusion avec les classes de base du composant.
Quand l’utiliser
Section intitulée « Quand l’utiliser »- Au sein de la bibliothèque de composants : chaque élément interne appelle
mergePt(props.pt?.icon, 'lh-button__icon')et obtient le class / style / attrs à accrocher. - Côté utilisateur, pour ajuster finement l’intérieur d’un composant via la prop
pt, sans avoir à percer avec:deep().
À éviter : la personnalisation au niveau du thème (utilisez themeVars) ; le simple ajout d’une classe (utilisez la prop class).
import { mergePt, type LhPtAttrs } from '@lh-ui/share/core/shared/pt'Types et fonction
Section intitulée « Types et fonction »export interface LhPtAttrs { class?: string | string[] | Record<string, boolean> style?: Record<string, string> attrs?: Record<string, any>}| Fonction | Signature | Rôle |
|---|---|---|
mergePt |
(pt: LhPtAttrs | undefined, baseClass: string) => { class: string[]; style: Record<string, string>; attrs: Record<string, any> } |
fusionne les props PT et la classe de base |
Les règles de fusion
Section intitulée « Les règles de fusion »baseClass se trouve toujours en tête du tableau, les classes de l’utilisateur suivent :
mergePt({ class: 'my-icon' }, 'lh-button__icon')// { class: ['lh-button__icon', 'my-icon'], style: {}, attrs: {} }
mergePt({ class: ['a', 'b'] }, 'lh-button__icon')// class: ['lh-button__icon', 'a', 'b']
mergePt({ class: { active: true, disabled: false } }, 'lh-button__icon')// class: ['lh-button__icon', 'active'] —— l'objet ne retient que les clés vraies
mergePt({ class: 'a b ' }, 'lh-button__icon')// class: ['lh-button__icon', 'a', 'b'] —— la chaîne est découpée sur les espaces, les chaînes vides sont filtréesPourquoi baseClass vient en premier : la spécificité de la classe de base BEM ne doit pas être écrasée par les classes de l’utilisateur (à spécificité égale, la dernière écrite l’emporte). Le modificateur --primary du composant doit continuer de couvrir le my-icon de l’utilisateur.
style / attrs
Section intitulée « style / attrs »mergePt(undefined, 'lh-button__icon')// { class: ['lh-button__icon'], style: {}, attrs: {} } —— pt vide, tout est vide
mergePt({ style: { color: 'red' }, attrs: { 'data-x': '1' } }, 'lh-button__icon')// { class: ['lh-button__icon'], style: { color: 'red' }, attrs: { 'data-x': '1' } }Note : style / attrs sont transmis par référence, sans copie. La couche UI peut faire directement v-bind="merged.attrs" / :style="merged.style" ; ne mutez pas la valeur renvoyée au sein du composant.
Exemples d’utilisation
Section intitulée « Exemples d’utilisation »Au sein du composant (l’icône du bouton)
Section intitulée « Au sein du composant (l’icône du bouton) »// Composant buttonconst iconPt = computed(() => mergePt(props.pt?.icon, 'lh-button__icon'))<template> <button class="lh-button"> <i v-if="icon" v-bind="iconPt.attrs" :class="iconPt.class" :style="iconPt.style" /> <span><slot /></span> </button></template>Côté utilisateur
Section intitulée « Côté utilisateur »<lh-button :pt="{ icon: { class: 'text-lg', style: { marginRight: '4px' } }, $root: { attrs: { 'data-test': 'submit' } }, }"> Soumettre</lh-button>const iconPt = mergePt(pt?.icon, 'lh-button__icon')
return ( <button className="lh-button"> {icon && <i className={iconPt.class.join(' ')} style={iconPt.style} {...iconPt.attrs} />} </button>)Points d’attention
Section intitulée « Points d’attention »- Une fusion superficielle, pas de deepMerge : concaténation au niveau tableau pour
class, remplacement du paquet pourstyle/attrs. Une fusion profonde n’aurait aucun sens ici (class est une liste, pas un arbre). - Un
ptvide renvoie un objet entièrement vide : la couche UI peut déstructérer sans réfléchir, sans test de vacuité. - La classe renvoyée est un tableau : le
:classde Vue accepte les tableaux, React a besoin d’un.join(' '). - La classe de base est obligatoire :
mergePt(pt, '')produit un tableau dont le premier élément est une chaîne vide — la classe de base BEM est l’ancre des styles, chaque élément interne doit en avoir une.
@lh-ui/share/core/pt → mergePt( )(填好参数后点运行)Copyright © 2024-2026 FengMo WenXue