Erstellen Sie flexible Layout- und zusammengesetzte UI -Komponenten, ohne dass beliebige benutzerdefinierte Requisiten definiert werden müssen.
npm i macro-components
import React from 'react'
import styled from 'styled-components'
import Macro from 'macro-components'
import { space , fontSize , color } from 'styled-system'
// Define some styled-components
const Box = styled . div ` ${ space } ${ fontSize } ${ color } `
Box . displayName = 'Box'
const Image = styled . img `
max-width: 100%;
height: auto;
${ space }
`
Image . displayName = 'Image'
const Heading = styled . h2 ` ${ space } ${ fontSize } ${ color } `
Heading . displayName = 'Heading'
const Text = styled . div ` ${ space } ${ fontSize } ${ color } `
Text . displayName = 'Text'
// create a macro function with the UI components you intend to use
const macro = Macro ( {
Image ,
Heading ,
Text
} )
// Create a macro-component
const MediaObject = macro ( ( {
Image ,
Heading ,
Text
} ) => (
< Flex p = { 2 } align = 'center' >
< Box width = { 128 } >
{ Image }
</ Box >
< Box >
{ Heading }
{ Text }
</ Box >
</ Flex >
) ) import MediaObject from './MediaObject'
// get the macro component's child components
const { Image , Heading , Text } = MediaObject
// Use the macro-component by passing the components as children
const App = props => (
< div >
< MediaObject >
< Image src = 'kitten.png' />
< Heading >
Hello
</ Heading >
< Text >
This component keeps its tree structure but still allows for regular composition.
</ Text >
</ MediaObject >
</ div >
) Hinweis: Makrokomponenten sollen nur mit bestimmten untergeordneten Komponenten arbeiten. Wenn Sie Slots definieren möchten, finden Sie im Abschnitt Alternativen unten.
Oft ist es am besten, React-Komposition und props.children zu verwenden. Children, um eine Benutzeroberfläche zu erstellen, die aus mehreren Elementen besteht. Manchmal möchten Sie jedoch möglicherweise größere zusammengesetzte Komponenten mit eingekapselten Baumstrukturen für Layout oder Erstellen von Bootstrap-ähnlichen UI-Komponenten wie Panels, Karten oder Warnungen erstellen. Mit dieser Bibliothek können Sie zusammengesetzte Komponenten mit eingekapselten DOM -Strukturen erstellen, ohne die APIs von willkürlichen Props zu definieren und genau wie jede andere React -Zusammensetzung zu funktionieren.
Dies kann dazu beitragen, dass Ihre Komponenten -API -Oberfläche klein und leichter zu warten ist.
Wenn Sie feststellen, dass Sie zusammengesetzte React -Komponenten erstellen, die nicht den Datenstrukturen zuordnen, wie in React in React beschrieben, ist dieses Modul für Sie vorgesehen.
Macro(componentsObject)(elementFunction)
Gibt eine React -Komponente mit einer komponierbaren API zurück, die die Baumlayoutstruktur hält.
const Banner = Macro ( {
// pass a components object
Heading ,
Subhead
} ) ( ( {
// the element function receives child elements
// named according to the components object
Heading ,
Subhead
} ) => (
< Box p = { 3 } color = 'white' bg = 'blue' >
{ Heading }
{ Subhead }
</ Box >
) Das elementFunction -Argument wird mit einem Objekt von Elementen aufgerufen, die auf dem an die Makrofunktion übergebenen componentsObject basieren. Die Verwendung der oben genannten Bannerkomponente sieht ungefähr wie das Folgende aus.
import Banner from './Banner'
const App = ( ) => (
< Banner >
< Banner . Heading > Hello </ Banner . Heading >
< Banner . Subhead > Subhead </ Banner . Subhead >
</ Banner >
)Das Komponentenobjekt wird verwendet, um zu definieren, welche Komponenten die Makrokomponente als Kinder akzeptiert.
Die Elementfunktion ähnelt einer React -Komponente, empfängt jedoch ein Element -Objekt als erstes Argument und Requisiten als zweite. Das Element -Objekt wird aus seinen Kindern erstellt und soll die Einkapselung von Zusammensetzungs- und Elementstrukturen erleichtern.
In der Makrokomponente wird die Elementfunktion mit den Elementenobjekten und den Requisiten aufgerufen: elementFunction(elementsObject, props) .
// example
const elFunc = ( { Heading , Text , } , props ) => (
< header >
{ Heading }
{ Text }
</ header >
)
const Heading = styled . h2 ``
const Text = styled . div ``
const componentsObj = {
Heading ,
Text
}
const SectionHeader = Macro ( componentsObj ) ( elFunc ) Für ein Element, das nicht als Kind an die Makrokomponente übergeben wird, wird die Elementfunktion undefined und reagiert dieses Element nicht. Dies ist nützlich, um optionale Kinder konditionell wegzulassen
const macro = Macro ( { Icon , Text , CloseButton } )
const Message = macro ( {
Icon ,
Text ,
CloseButton
} ) = > (
< Flex p = { 2 } bg = 'lightYellow' >
{ Icon }
{ Text }
< Box mx = 'auto' />
{ CloseButton }
</ Flex >
) import Message from './Message'
const { Text , CloseButton } = Message
// Omitting the Icon child element will render Message without an icon.
const message = (
< Message >
< Text > { props . message } </ Text >
< CloseButton
onClick = { props . dismissMessage }
/>
</ Message >
)Mit dem zweiten Argument, das an die Elementfunktion übergeben wurde, können Sie Requisiten an das Stammelement oder ein anderes Element innerhalb der Komponente übergeben.
const macro = Macro ( { Image , Text } )
const Card = macro ( ( {
Image ,
Text
} , props ) => (
< Box p = { 2 } bg = { props . bg } >
{ Image }
{ Text }
</ Box >
) ) // example usage
< Card bg = 'tomato' >
< Card . Image src = 'kittens.png' />
< Card . Text > Meow </ Card . Text >
</ Card >Verwenden Sie die Klonkomponente in einer Elementfunktion, um Standard -Requisiten auf die als Kinder übergebenen Elemente anzuwenden.
import Macro , { Clone } from 'macro-components'
import { Heading , Text } from './ui'
const macro = Macro ( { Heading , Text } )
const Header = macro ( ( { Heading , Text } ) => (
< Box p = { 2 } >
< Clone
element = { Heading }
fontSize = { 6 }
mb = { 2 }
/>
< Clone
element = { Text }
fontSize = { 3 }
/>
</ Box >
) )Um dieselbe Komponente zweimal zu verwenden, geben Sie ihm einen einzigartigen Schlüssel im KomponentenObject.
import React from 'react'
import Macro from 'macro-components'
import { Heading } from './ui'
const macro = Macro ( {
Heading : Heading ,
Subhead : Heading
} )
const Header = macro ( ( { Heading , Subhead } ) => (
< Box p = { 2 } >
{ Heading }
{ Subhead }
</ Box >
) ) < Header >
< Header . Heading > Hello </ Header . Heading >
< Header . Subhead > Subhead </ Header . Subhead >
</ Header >Um Layoutkomponenten zu erstellen, die nicht mit bestimmten untergeordneten Komponenten gekoppelt sind, ist es wahrscheinlich ein einfacherer Ansatz, Requisiten oder geordnete Kinder zu verwenden.
Mit den folgenden Lösungen können Sie beliebige Komponenten als Requisiten oder Kinder bestehen.
Siehe diese Diskussion für mehr.
// using custom props
const MyLayout = ( {
left ,
right
} ) => (
< Flex >
< Box width = { 128 } >
{ left }
</ Box >
< Box width = { 1 } >
{ right }
</ Box >
</ Flex >
)
< MyLayout
left = { (
< Image src = 'kitten.png' />
) }
right = { (
< Text > Meow </ Text >
) }
/ > // using ordered children
const Header = props => {
const [ first , second ] = React . Children . toArray ( props . children )
return (
< Box p = { 3 } >
{ first }
{ second }
</ Box >
)
}
< Header >
< Heading > First </ Heading >
< Text > Second < / Text>
</ Header > // using a children object
const Header = ( {
children : {
left ,
right
}
} ) => (
< Flex >
< Box >
{ left }
</ Box >
< Box width = { 1 } >
{ right }
</ Box >
</ Flex >
)
< Header >
{ {
left : (
< Image src = 'kitten.png' />
) ,
right : (
< Text > Meow </ Text >
)
} }
</ Header > MIT -Lizenz