Buat tata letak yang fleksibel dan komponen UI komposit tanpa perlu mendefinisikan alat peraga khusus sewenang -wenang.
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 >
) Catatan: Komponen makro dimaksudkan untuk hanya bekerja dengan komponen anak tertentu. Jika Anda ingin mendefinisikan slot , lihat bagian alternatif di bawah ini.
Seringkali yang terbaik adalah menggunakan komposisi dan props.children reaksi. Anak-anak untuk membuat UI yang terdiri dari banyak elemen, tetapi kadang-kadang Anda mungkin ingin membuat komponen komposit yang lebih besar dengan struktur pohon yang dienkapsulasi untuk tata letak atau membuat komponen UI seperti bootstrap seperti panel, kartu, atau peringatan. Perpustakaan ini memungkinkan Anda membuat komponen komposit dengan struktur DOM yang dienkapsulasi tanpa perlu mendefinisikan alat peraga sewenang -wenang dan itu berfungsi seperti komposisi reaksi lainnya.
Ini dapat membantu memastikan bahwa area permukaan API komponen Anda tetap kecil dan lebih mudah dipelihara.
Jika Anda menemukan diri Anda membuat komponen reaksi komposit yang tidak memetakan ke struktur data, seperti yang dijelaskan dalam berpikir dalam React, maka modul ini ditujukan untuk Anda.
Macro(componentsObject)(elementFunction)
Mengembalikan komponen bereaksi dengan API yang dapat dikomposisi yang menjaga struktur tata letak pohon.
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 >
) Argumen elementFunction dipanggil dengan objek elemen berdasarkan componentsObject yang diteruskan ke fungsi makro. Menggunakan komponen spanduk di atas akan terlihat seperti berikut.
import Banner from './Banner'
const App = ( ) => (
< Banner >
< Banner . Heading > Hello </ Banner . Heading >
< Banner . Subhead > Subhead </ Banner . Subhead >
</ Banner >
)Objek komponen digunakan untuk menentukan komponen mana yang akan diterima komponen makro sebagai anak -anak.
Fungsi elemen mirip dengan komponen React, tetapi menerima objek elemen sebagai argumen pertama dan alat peraga sebagai yang kedua. Objek Elemen dibuat dari anak -anaknya dan dimaksudkan untuk membuat komposisi dan struktur elemen yang enkapsulasi lebih mudah.
Di dalam komponen makro, fungsi elemen dipanggil dengan objek elemen dan alat peraga: 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 ) Untuk elemen apa pun yang tidak dilewati sebagai anak ke komponen makro, fungsi elemen akan membuat undefined dan bereaksi tidak akan membuat elemen itu. Ini berguna untuk menghilangkan anak opsional secara kondisional
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 >
)Argumen kedua yang diteruskan ke fungsi elemen memungkinkan Anda untuk meneruskan alat peraga ke elemen root atau elemen lain dalam komponen.
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 >Untuk menerapkan alat peraga default pada elemen yang dilewati sebagai anak -anak, gunakan komponen klon dalam fungsi elemen.
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 >
) )Untuk menggunakan komponen yang sama dua kali, berikan kunci unik di ComponentsObject.
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 >Untuk membuat komponen tata letak yang tidak digabungkan dengan komponen anak tertentu, menggunakan alat peraga atau anak -anak yang dipesan mungkin merupakan pendekatan yang lebih sederhana.
Solusi di bawah ini memungkinkan Anda untuk melewati komponen sewenang -wenang sebagai alat peraga atau anak -anak.
Lihat diskusi ini untuk lebih lanjut.
// 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 > Lisensi MIT