React’te Güçlü Yeniden Kullanılabilir Kutu Bileşeni Oluşturun – JSManifest

React'te Güçlü Yeniden Kullanılabilir Kutu Bileşeni Oluşturun – JSManifest

Kutu bileşenleri en temel ancak güçlü Reaksiyon uygulamalarında kullanılacak bileşenler. Davranışları basittir, ancak bu basitlik, daha karmaşık bileşenleri bir araya getirmenin temel temelidir ve modern kullanıcı arayüzleri oluşturmak için sonsuz olasılıklara izin verir.

Bu yazıda, fonksiyon içinde sadece birkaç basit uygulama ile tepki veren güçlü bir yeniden kullanılabilir kutu bileşeni oluşturacağız.

Vakfı yaz

Yapacağımız ilk şey kendimizi tanımlamaktır. Box ile bileşen çıplak minimum şöyle:

function Box({ children, ...props }) {
  return <div {...props}>{children}</div>
}

Burada zaten görülecek iki önemli şey var:

  1. Seçtiğimiz eleman div. Bu, her yeniden kullanılabilir bileşenin başlaması gereken DOM’daki en temel öğedir. Varsayılan olarak bir tüm blok. Öğe, tam tersi olmak yerine, gerekirse yapılandırmamız gereken tüm genişliği kaplıyorsa daha sezgiseldir.
  2. Biz yıkmak children ve manuel olarak bizim için uygula Box bileşen. Bunu her zaman, her bileşenle yapmayı seviyorum. çocukları bekliyor Çünkü o bir net gösterge ebeveynin bazı tepki düğümlerinden geçmeyi bekleyeceği. Aynı zamanda en iyi uygulamadır ve bu şekilde yapmak, içeri aktarmak yerine daha fazla fayda sağlar. props gizemli bir şekilde uygulandığı yer. Gizem, React’in bildirimsel doğasına aykırıdır.

Artık onu işimizde kullanabiliriz. App bileşen:

import React from 'react'

function Box({ children, ...props }) {
  return <div {...props}>{children}</div>
}

export default function App() {
  return <Box>Sally Montgomery</Box>
}

Bu öğretici uğruna, devam ederken neyin uygulandığını açıkça görebilmemiz için ana bileşende önceden bazı stillerden geçeceğiz:

import React from 'react'

function Box({ children, ...props }) {
  return <div {...props}>{children}</div>
}

export default function App() {
  return (
    <Box
      style={{
        backgroundColor: '#333',
        borderRadius: 4,
        color: '#eee',
        minHeight: 200,
        padding: 12,
        width: 300,
      }}
    >
      Sally Montgomery
    </Box>
  )
}

Ebeveyn Olmak için ebeveyn

bizim yeniden kullanılabilir Box bileşen abilir burada bitecek, ancak içine daha fazla yetenek sıkıştırmak istiyorsak yeniden kullanılabilirlikteki mevcut yeteneğini azaltmadan bizim özelleştirebiliriz Box daha fazla sahne kabul etmek ve bunları işlemek için uygulama ebeveynin onları yönetmesine izin vermeden.

Ebeveynin olduğu durumlar vardır. meli bazı sahne malzemelerini ele al, ama olmalılar isteyen yapılandırabilmek gibi bunları işlemek için style zaten yukarıda sahip olduğumuz nesne.

bizim içinde App bileşen bazı stil aksesuarları uyguladık:

export default function App() {
  return (
    <Box
      style={{
        backgroundColor: '#333',
        borderRadius: 4,
        color: '#eee',
        minHeight: 200,
        padding: 12,
        width: 300,
      }}
    >
      Sally Montgomery
    </Box>
  )
}

Bunu neden yaptık? Çünkü biz olmasaydık Box şöyle görünecek:

boş-tepki kutusu-bileşen1.png

Bunu düşün. Box bileşenimizi içe aktaran her bileşen içeri aktarılacak mı? style her zaman? Büyük olasılıkla, aksi takdirde sadece bir div öğe.

Ebeveynin bir açıklama yapmasına gerek kalmadan bazı stil aksesuarlarının geçmesine izin verebiliriz. style her zaman nesne:

(not: Bu yazının ilerleyen kısımlarında kullanacağım ekstra aksesuarlar ekledim)

function Box({
  children,
  backgroundColor,
  border,
  borderRadius,
  color,
  overflow,
  fontFamily,
  fontSize,
  fontWeight,
  minHeight,
  margin,
  padding,
  width,
  textAlign,
  style,
  ...props
}) {
  return (
    <div
      {...props}
      style={{
        border,
        backgroundColor,
        borderRadius,
        color,
        fontFamily,
        fontSize,
        fontWeight,
        overflow,
        minHeight,
        margin,
        padding,
        width,
        textAlign,
        ...style,
      }}
    >
      {children}
    </div>
  )
}

Bu şekilde bileşenlerimiz bir bütün olarak manuel olarak geçmek zorunda kalmayacak style birkaç stili değiştirmek için nesne:

export default function App() {
  return (
    <Box
      backgroundColor="#333"
      borderRadius={4}
      color="#eee"
      minHeight={200}
      padding={12}
      width={300}
    >
      Sally Montgomery
    </Box>
  )
}

Ayrıca içimizde olduğundan emin olduk. Box bileşeni yerleştirdiğimiz style diğerlerini geçersiz kılabilmesi için en son destek ebeveyn ne zaman isterse:

tepki-kutusu-bileşen-yayılmış-stil-nesne-last1.png

Bu, popüler kütüphanelerin sevdiği çok uygun bir stratejidir. @çakra-ui/tepki geliştirme deneyimini iyileştiren şeyi yapın (buradaki amaç kullanıcıları bu yola yönlendirmek olduğu için bu gönderinin yapmayacağı şeyi tamamen özelleştirdiler).

Daha hızlı, daha kolay, kodu ve ortak plakayı azaltır.

hadi kullanalım Box oluşturmak için bileşen kart:

export default function App() {
  return (
    <Box
      backgroundColor="#333"
      borderRadius={4}
      color="#eee"
      minHeight={200}
      padding={12}
      width={300}
    >
      <Box>
        <img alt="Profile" src="./images/woman.png" style={{ width: 70 }} />
      </Box>
      <Box>Sally Montgomery</Box>
      <Box>
        About me: I am a hard working individual who strives for success. I have
        a puppy named Cookie that I love very much because she always prevents
        me from falling into emotional thoughts and keeps me going.
      </Box>
      <Box></Box>
    </Box>
  )
}

kutu-kart-bileşen-in-react1.png

(Kadın avatarı şuradan alınmıştır: ücretsiz)

Şimdiden iyi görünüyorsun! Ancak kadın imajımıza biraz boşluk, yazı tipi stili ve kenarlık uygulamamız gerekiyor, bu bizim için kolaylaştırdığımız için kolayca yapılabilir. Box.

Daha Fazlasını Yapın, Daha Az Çalışın

export default function App() {
  return (
    <Box
      backgroundColor="#333"
      borderRadius={4}
      color="#eee"
      minHeight={200}
      padding={20}
      width={300}
    >
      <Box
        width={80}
        border="4px solid cyan"
        backgroundColor="#fff"
        borderRadius="50%"
        overflow="hidden"
      >
        <img alt="Profile" src={woman} style={{ width: '100%' }} />
      </Box>
      <Box fontFamily="Helvetica" fontSize="1.3rem" padding="10px 0">
        Sally Montgomery
      </Box>
      <Box fontFamily="Helvetica" fontWeight={300}>
        About me: I am a hard working individual who strives for success. I have
        a puppy named Cookie that I love very much because she always prevents
        me from falling into emotional thoughts and keeps me going.
      </Box>
      <Box></Box>
    </Box>
  )
}

daha iyi-tepki-kart-bileşen-fancy1.png

daha da optimize edebiliriz Box Bileşenlerini varsayılan olarak ayarlayarak ana bileşenlerin birlikte çalışmasını daha da kolaylaştırmak için bileşen. Her uygulamanın bir dizi varsayılanı vardır yazı tipi uygulama boyunca kullanılacak stiller, bu yüzden Box yazı tipinde bu aksesuarlar için varsayılan:

function Box({
  children,
  backgroundColor,
  border,
  borderRadius,
  color,
  overflow,
  fontFamily = 'Helvetica',
  fontSize = '1rem',
  fontWeight = 300,
  minHeight,
  margin,
  padding,
  width,
  textAlign,
  style,
  ...props
}) {
  return (
    <div
      {...props}
      style={{
        border,
        backgroundColor,
        borderRadius,
        color,
        fontFamily,
        fontSize,
        fontWeight,
        overflow,
        minHeight,
        margin,
        padding,
        width,
        textAlign,
        ...style,
      }}
    >
      {children}
    </div>
  )
}

Artık kodlarımızdaki bazı kodları kaldırabiliriz. App bizim beri Box bunları varsayılan olarak işler:

export default function App() {
  return (
    <Box
      backgroundColor="#333"
      borderRadius={4}
      color="#eee"
      minHeight={200}
      padding={20}
      width={300}
    >
      <Box
        width={80}
        border="4px solid cyan"
        backgroundColor="#fff"
        borderRadius="50%"
        overflow="hidden"
      >
        <img alt="Profile" src={woman} style={{ width: '100%' }} />
      </Box>
      <Box fontSize="1.3rem" padding="10px 0">
        Sally Montgomery
      </Box>
      <Box>
        About me: I am a hard working individual who strives for success. I have
        a puppy named Cookie that I love very much because she always prevents
        me from falling into emotional thoughts and keeps me going.
      </Box>
      <Box></Box>
    </Box>
  )
}

Bizimle ilgili harika bir şey Box bileşen, olabileceği oluşan yaratmak daha karmaşık yeniden kullanılabilir bileşenler. Burası bizim yeniden kullanılabilirliğimizin olduğu yer Box bileşen Gerçekten parlıyor çünkü zaten temel kalıpları soyutluyor, böylece temel ihtiyaçlar hakkında endişelenmeden her yerde kullanılabilecekler:

function Card({ avatar, title, children, ...rootProps }) {
  return (
    <Box
      backgroundColor="#333"
      borderRadius={4}
      color="#eee"
      minHeight={200}
      padding={20}
      width={300}
      {...rootProps}
    >
      {avatar ? (
        <Box
          width={80}
          border="4px solid cyan"
          backgroundColor="#fff"
          borderRadius="50%"
          overflow="hidden"
        >
          {avatar}
        </Box>
      ) : null}
      {title ? (
        <Box fontSize="1.3rem" padding="10px 0">
          {title}
        </Box>
      ) : null}
      {children ? <Box>{children}</Box> : null}
    </Box>
  )
}

export default function App() {
  return (
    <Card
      avatar={<img alt="Profile" src={woman} style={{ width: '100%' }} />}
      title="Sally Montgomery"
    >
      About me: I am a hard working individual who strives for success. I have a
      puppy named Cookie that I love very much because she always prevents me
      from falling into emotional thoughts and keeps me going.
    </Card>
  )
}

Kazan Plakası Geri Döndüğünde. Daha Sert Geri Vurursun

Burada bir gün diyebiliriz. Ama yakından bakarsan, görmeye başlıyoruz Box her yerde, bu yüzden sonunda tekrar ortak kod yazma sorununu ortaya çıkarır.

Bazı tepki kitaplıklarının yararlandığı ve bizim için kullanabileceğimiz güçlü bir strateji var. Box bileşen. Ebeveynin özel bir tepki öğesi, öğe etiketi veya bileşen olarak prop olarak geçmesine izin veren bir parametre bildirebiliriz:

function Box({
  as: asProp = 'div',
  children,
  backgroundColor,
  border,
  borderRadius,
  color,
  overflow,
  fontFamily = 'Helvetica',
  fontSize = '1rem',
  fontWeight = 300,
  minHeight,
  margin,
  padding,
  width,
  textAlign,
  style,
  ...props
}) {
  const Component = asProp

  return (
    <Component
      {...props}
      style={{
        border,
        backgroundColor,
        borderRadius,
        color,
        fontFamily,
        fontSize,
        fontWeight,
        overflow,
        minHeight,
        margin,
        padding,
        width,
        textAlign,
        ...style,
      }}
    >
      {children}
    </Component>
  )
}

tepki-kutusu-bileşen-özel-as-prop1.png

Daha Az Kaynak

Bununla birlikte, bizim gibi yerlerde kullanıldığında kullanışlı olabilir. Card:

tepki-kutusu-bileşen-as-img-element-reusable1.png

Bunu yapmak güzel bir fayda sağlar: Kaldırırız bir bileşen eksik sanal dom içinde oluşturuluyor. Daha fazla bileşende yoğun olarak kullanıldığında GPU’nuz size teşekkür edecektir.

Tembelliği Teşvik Etmek

Bir başka şey. Ayrıca, sahne malzemelerinin tembel yollarla uygulanmasına da olanak tanır. Örneğin, aşağıdan beri avatar sahnelerimizi oluşturduğumuzda Box doğrudan bundan faydalanabileceğimiz bir bileşen olabilir ve bunun gibi süper tembel olabiliriz:

const getCardAvatarProps = (avatar) => {
  return {
    as: 'img',
    width: 80,
    border: '4px solid cyan',
    backgroundColor: '#fff',
    borderRadius: '50%',
    overflow: 'hidden',
    ...(typeof avatar === 'string'
      ? { src: avatar }
      : React.isValidElement(avatar)
      ? { children: avatar }
      : avatar),
  }
}

function Card({ avatar, title, children, ...rootProps }) {
  return (
    <Box
      backgroundColor="#333"
      borderRadius={4}
      color="#eee"
      minHeight={200}
      padding={20}
      width={300}
      {...rootProps}
    >
      <Box {...getCardAvatarProps(avatar)} />>
      {title ? (
        <Box fontSize="1.3rem" padding="10px 0">
          {title}
        </Box>
      ) : null}
      {children ? <Box>{children}</Box> : null}
    </Box>
  )
}

ön ayarlar

Ve listemize ekleyebileceğimiz bir başka yararlı şey Box belirli aksesuarlar için bir dizi “ön ayar”a izin vermektir.

Örneğin, izin verebiliriz fontSize olarak geçirilecek 'xl', 'lg', 'md', 'sm'veya 'xs'. Bunlardan hiçbiri sağlanmazsa, yalnızca sağlanan değeri uygular. Bu iter Box ile çalışmak daha kolay olma yeteneklerinde daha da ileri:

function Box({
  as: asProp = 'div',
  children,
  backgroundColor,
  border,
  borderRadius,
  color,
  mode = 'default',
  overflow,
  fontFamily = 'Helvetica',
  fontSize = '1rem',
  fontWeight = 300,
  minHeight,
  margin,
  padding,
  width,
  textAlign,
  style,
  ...props
}) {
  const Component = asProp

  let modeStyles

  if (mode === 'modal') {
    modeStyles = {
      display: 'flex',
      justifyContent: 'center',
      alignItems: 'center',
      border: '12px solid #19A8F7',
      flexDirection: 'column',
      backgroundColor: '#1F3F50',
      color: '#eee',
    }
  } else if (mode === 'card') {
    modeStyles = {
      backgroundColor: '#fff',
      color: 'rgba(0, 0, 0, 0.75)',
      paddingBottom: 30,
    }
  }

  const otherStyles = {
    border,
    backgroundColor,
    borderRadius,
    color,
    fontFamily,
    fontSize,
    fontWeight,
    overflow,
    minHeight,
    margin,
    padding,
    width,
    textAlign,
  }

  if (fontSize) {
    if (fontSize === 'xl') otherStyles.fontSize = '2rem'
    else if (fontSize === 'lg') otherStyles.fontSize = '1.5rem'
    else if (fontSize === 'md') otherStyles.fontSize = '1.2rem'
    else if (fontSize === 'sm') otherStyles.fontSize = '1rem'
    else if (fontSize === 'xs') otherStyles.fontSize = '0.8rem'
  }

  return (
    <Component
      {...props}
      style={{
        ...otherStyles,
        ...style,
        ...modeStyles,
      }}
    >
      {children}
    </Component>
  )
}

bu Card bileşenin bunu bilmesine bile gerek yoktur ve sağladığı faydaları elde etmek için sahne öğelerini iletebilir. Örneğin, işlenirken title prop sadece bir nesneyi alabilir ve onu bir gün olarak adlandırabilir:

const getCardTitleProps = (title) => {
  return typeof title === 'string' ? { children: title } : title
}

function Card({ avatar, title, children, mode, ...rootProps }) {
  return (
    <Box
      backgroundColor="#333"
      borderRadius={4}
      color="#eee"
      minHeight={200}
      padding={20}
      width={300}
      mode={mode}
      {...rootProps}
    >
      {avatar ? (
        <Box
          as={typeof avatar === 'string' ? 'img' : undefined}
          width={80}
          border="4px solid cyan"
          backgroundColor="#fff"
          borderRadius="50%"
          overflow="hidden"
          src={typeof avatar === 'string' ? avatar : undefined}
        >
          {typeof avatar === 'string' ? null : avatar}
        </Box>
      ) : null}
      <Box fontSize="1.3rem" padding="10px 0" {...getCardTitleProps(title)} />
      {children ? <Box>{children}</Box> : null}
    </Box>
  )
}

kart-tepki-bileşen-olmak-yeniden kullanılabilir-in-font-styles.png

Uygulamanızda uzmanlaşmak için bir araya getirme

Burada bahsetmek istediğim son bir şey, benim için yapmayı sevdiğim şey. Box uygulamam için özelleşmiş bileşenler. oluşturmak için yararlıdır mode duruma göre stilleri değiştirecek olan ve farklı bir “hissetmek” ona:

function Box({
  as: asProp = 'div',
  children,
  backgroundColor,
  border,
  borderRadius,
  color,
  mode = 'default',
  overflow,
  fontFamily = 'Helvetica',
  fontSize = '1rem',
  fontWeight = 300,
  minHeight,
  margin,
  padding,
  width,
  textAlign,
  style,
  ...props
}) {
  const Component = asProp

  let modeStyles

  if (mode === 'modal') {
    modeStyles = {
      display: 'flex',
      justifyContent: 'center',
      alignItems: 'center',
      border: '12px solid #19A8F7',
      flexDirection: 'column',
      backgroundColor: '#1F3F50',
      color: '#eee',
    }
  } else if (mode === 'card') {
    modeStyles = {
      backgroundColor: '#fff',
      color: 'rgba(0, 0, 0, 0.75)',
      paddingBottom: 30,
    }
  }

  return (
    <Component
      {...props}
      style={{
        border,
        backgroundColor,
        borderRadius,
        color,
        fontFamily,
        fontSize,
        fontWeight,
        overflow,
        minHeight,
        margin,
        padding,
        width,
        textAlign,
        ...style,
        ...modeStyles,
      }}
    >
      {children}
    </Component>
  )
}
export default function App() {
  return (
    <Card avatar={woman} title="Sally Montgomery" mode="modal">
      About me: I am a hard working individual who strives for success. I have a
      puppy named Cookie that I love very much because she always prevents me
      from falling into emotional thoughts and keeps me going.
    </Card>
  )
}

Sonuç:

tepki-kart-bileşen-modal-modu-reusable1.png

export default function App() {
  return (
    <Card avatar={woman} title="Sally Montgomery" mode="card">
      About me: I am a hard working individual who strives for success. I have a
      puppy named Cookie that I love very much because she always prevents me
      from falling into emotional thoughts and keeps me going.
    </Card>
  )
}

Sonuç:

kart-bileşen-in-tepki-tekrar kullanılabilir1-kart-mode.png

Özelleştirilmiş stiller uygularken, herhangi bir genişlik/yükseklik veya herhangi bir konumlandırma ayarlamamak, bunun yerine ebeveynin bunları özelleştirmesine izin vermek en iyisidir. Aksi takdirde, örtüşen öğeler gibi bir sorunla karşılaştıklarında, Box kendi bileşenleriyle kombinasyon halinde satır içi.

Çözüm

Ve bu yazının sonu burada bitiyor! Bunu değerli bulduğunuzu ve gelecekte daha fazlasını aradığınızı fark ettim!

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.