Özyinelemeyi Kullanarak React’te Modern Dinamik Kenar Çubuğu Menüsü Oluşturma – JSManifest

Özyinelemeyi Kullanarak React'te Modern Dinamik Kenar Çubuğu Menüsü Oluşturma – JSManifest

Web sayfalarında, web sayfalarındaki kenar çubukları, gezinme işlevleri nedeniyle sayfada bulunan en kullanışlı bileşenlerden biridir.

Bugün tepki vererek modern bir kenar çubuğu oluşturacağız. özyineleme. Özyineleme, bir fonksiyonun basitçe kendisini çağırdığı bir tekniktir. defalarca bir koşul sağlanana kadar. bu üç özyineleme kuralı bu gönderide özyineleme kullanırken geçerlidir:

  1. İşlev, kendini yok eden bir koşula sahip olmalıdır.
  2. Fonksiyonun bir temel koşulu olmalıdır
  3. İşlev kendini çağırıyor olmalı

Kenar çubukları, dikkat düzeyi ilk sırada gelmese bile, bir web sayfası için gerçekten çok önemlidir. Bunun nedeni, kullanıcıların mantıksal bir gezinme menüsü yerine ilgilenebilecekleri içerik gibi farklı şekillerde gezinmelerine yardımcı olabilmeleridir.

Ama neden kenar çubukları için özyineleme kullanmak isteyelim ki? Kenar çubuğu öğelerinizi manuel olarak yazmaktan farklı olarak ne fark eder? İnternette bir süre gezindiyseniz, bir web sitesinin kenar çubuğuna rastlamış ve bazı kenar çubuğu öğelerinin alt bölümleri olduğunu fark etmiş olabilirsiniz. Bazı sitelerde, belirli öğeleri aşağıdakilere dayalı olarak gizleyen veya oluşturan kenar çubukları vardır. sayfa rotası kullanıcıya gitti. Yani güçlü!

Örneğin, kırmızı dairenin içindeki aşağıdaki resme bakarsak, editörler kısım, kenar çubuğunun bir öğesidir ve hemen aşağıdaki 3 öğe (Kod Düzenleyici, indirim, Metin düzeltici) alt bölümler şunlardır:

Bu yazının sonunda, görünüşte karmaşık olan bu kenar çubuğunun aslında 50 satır kod altında! Ne?!

Burada bir temel Bu gönderideki kenar çubuğu bileşenini biraz daha şık olacak şekilde nasıl genişletebileceğinize ve yine de temiz hissini koruyabileceğinize dair bir örnek:

genişletilmiş özyineleme kullanarak tepki veren modern dinamik kenar çubuğu

Lafı fazla uzatmadan başlayalım!

Bu derste, hızlı bir şekilde bir tepki projesi oluşturacağız. oluştur-tepki-uygulaması.

(Deponun bir kopyasını github’dan almak istiyorsanız, tıklayın burada).

Devam edin ve aşağıdaki komutu kullanarak bir proje oluşturun. Bu eğitim için projemizi arayacağım modern kenar çubuğu.

npx create-react-app modern-sidebar

Şimdi bittiğinde dizine gidin:

Ana girişin içinde src/index.js sadece bileşene odaklanabilmemiz için onu biraz temizleyeceğiz:

import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import './styles.css'
import * as serviceWorker from './serviceWorker'

ReactDOM.render(<App />, document.getElementById('root'))

serviceWorker.unregister()

Şimdi oluştur src/App.js:

import React from 'react'

const App = () => <div />

export default App

App bizimkileri ithal edecek ve kullanacak Sidebar oluşturarak bileşen Sidebar.jsöyleyse devam edelim ve şunu oluşturalım:

import React from 'react'

function Sidebar() {
  return null
}

export default Sidebar

Şimdi bir CSS kitaplığı kuracağım, ancak aslında kenar çubuğunun aynı çalışma işlevselliğini onsuz oluşturacağız. Bunu yapmamın nedeni, kullanıma hazır simgelere sahip olmanın yanı sıra ek dalgalanma efektlerini görmeyi sevdiğim için 🙂

npm install @material-ui/core @material-ui/icons

Bu yüklendikten sonra, kullanıcı arayüzünde kenar çubuğumuzun üzerine inşa edileceği bir temel yapı düşünmemiz gerekiyor. Bir çözüm, sırasız listeyi kullanmaktır (<ul>) liste öğelerini oluşturan öğe (<li>). ithal edeceğiz List ve ListItem itibaren @material-ui/core Beri List bileşen aslında bir ul eleman ve ListItem bileşen aslında bir li.

Bunun güvenimizi artırmak için nasıl görünebileceğini görselleştirmek için kenar çubuğundaki birkaç öğeyi sabit kodlamaya başlayalım. Bazen biraz ekstra güven, üretkenliğimizi artırmaya yardımcı olabilir:

import React from 'react'
import List from '@material-ui/core/List'
import ListItem from '@material-ui/core/ListItem'
import ListItemText from '@material-ui/core/ListItemText'

function Sidebar() {
  return (
    <List disablePadding dense>
      <ListItem button>
        <ListItemText>Home</ListItemText>
      </ListItem>
      <ListItem button>
        <ListItemText>Billing</ListItemText>
      </ListItem>
      <ListItem button>
        <ListItemText>Settings</ListItemText>
      </ListItem>
    </List>
  )
}

export default Sidebar

(disablePadding ve dense öğelerin her birinin boyutunu biraz küçültmek için kullanıldı ve button pervane, çarpıcı dalgalanma efekti eklemek için kullanıldı).

Şimdiye kadar sahip olduğumuz şey bu:

kenar çubuğu öğeleri tepki olarak kodlanmış öğeleri listeler

Şimdi güvenimizi artırdığımıza göre, devam edelim ve tanımlayalım props.itemsHangi Sidebar öğelerini işlemek için tüketecektir.

Bununla birlikte, biz de bir items kenar çubuğu menüsündeki her bir öğeyi temsil eden nesneler dizisi olan prop. İşlevselliği olabildiğince basit tutmak istiyoruz, aksi takdirde bileşeni hızlı bir şekilde karmaşık hale getirebiliriz.

İlk önce öğeleri oluşturalım App bileşen ve olarak iletin props.items ile Sidebar:

import React from 'react'
import Sidebar from './Sidebar'

const items = [
  { name: 'home', label: 'Home' },
  { name: 'billing', label: 'Billing' },
  { name: 'settings', label: 'Settings' },
]

function App() {
  return (
    <div>
      <Sidebar items={items} />
    </div>
  )
}

export default App

şimdi güncelleyeceğiz Sidebar bu dizi yapısını yansıtacak bileşen:

import React from 'react'
import List from '@material-ui/core/List'
import ListItem from '@material-ui/core/ListItem'
import ListItemText from '@material-ui/core/ListItemText'

function Sidebar({ items }) {
  return (
    <List disablePadding dense>
      {items.map(({ label, name, ...rest }) => (
        <ListItem key={name} button {...rest}>
          <ListItemText>{label}</ListItemText>
        </ListItem>
      ))}
    </List>
  )
}

export default Sidebar

Fark etmiş olabileceğiniz bir şey, kenar çubuğumuzun sadece çok büyük! Yançubuklar genellikle ekranın bir tarafını kaplar. Yani yapacağımız şey genişliğini uygun bir boyuta küçültmek. Devam edeceğiz ve bir max-width nın-nin 200px üstünde. Yani bir oluşturacağız div bizi saran eleman List bileşen.

Başka bir tane yaratmamızın nedeni div üzerine stilleri doğrudan uygulamak yerine List bileşen, yapmak istemediğimiz için List genişlik boyutundan sorumludur. Bu şekilde, gelecekte soyutlamayı seçebiliriz. List boyutuna bağlı olarak herhangi bir boyuta uyum sağlayabildiği yeniden kullanılabilir bir kenar çubuğu bileşenine dönüştürün. ebeveyn eleman:

İşte Sidebar.js bileşen:

import React from 'react'
import List from '@material-ui/core/List'
import ListItem from '@material-ui/core/ListItem'
import ListItemText from '@material-ui/core/ListItemText'

function Sidebar({ items }) {
  return (
    <div className="sidebar">
      <List disablePadding dense>
        {items.map(({ label, name, ...rest }) => (
          <ListItem key={name} button {...rest}>
            <ListItemText>{label}</ListItemText>
          </ListItem>
        ))}
      </List>
    </div>
  )
}

export default Sidebar

Ve içeride index.css için css stillerini tanımladık sidebar sınıf:

.sidebar {
  max-width: 240px;
  border: 1px solid rgba(0, 0, 0, 0.1);
}

Material-UI aslında kendi CSS stil mekanizması JS içinde CSS yaklaşımını kullanarak. Ancak işleri gereksiz yere karmaşık tutmak için bu makalede normal CSS’ye bağlı kalacağız.

Bunu zaten bu kadar basit bırakabilir ve bir gün olarak adlandırabiliriz. Ancak, alt öğeleri desteklemez. Bir kenar çubuğu öğesini tıklatabilmek ve varsa alt öğeler listesini aşağı indirmesini istiyoruz. Alt öğelere sahip olmak, ek öğeleri başka bir kenar çubuğunda gruplayarak kenar çubuğunu düzenlemeye yardımcı olur bölüm:

tepki veren alt öğelere sahip kenar çubuğu öğeleri

Bu özelliği desteklememizin yolu, içeride başka bir seçeneğe izin vermektir. her biri bileşenin alt öğelerini algılamak için kullanacağı kenar çubuğu öğesi. (hissedebiliyor musun özyineleme gelen?)

Öğe dizimizi değiştirelim App alt öğelerde iletilecek bileşen:

import React from 'react'
import Sidebar from './Sidebar'

const items = [
  { name: 'home', label: 'Home' },
  {
    name: 'billing',
    label: 'Billing',
    items: [
      { name: 'statements', label: 'Statements' },
      { name: 'reports', label: 'Reports' },
    ],
  },
  {
    name: 'settings',
    label: 'Settings',
    items: [{ name: 'profile', label: 'Profile' }],
  },
]

function App() {
  return (
    <div>
      <Sidebar items={items} />
    </div>
  )
}

export default App

Bir kenar çubuğu öğesinin oluşturulabilmesi için alt öğeleriçin izlemek zorunda kalacağız items kenar çubuğu öğelerini oluştururken özellik:

function Sidebar({ items }) {
  return (
    <div className="sidebar">
      <List disablePadding dense>
        {items.map(({ label, name, items: subItems, ...rest }) => (
          <ListItem style={{ paddingLeft: 18 }} key={name} button {...rest}>
            <ListItemText>{label}</ListItemText>
            {Array.isArray(subItems) ? (
              <List disablePadding>
                {subItems.map((subItem) => (
                  <ListItem key={subItem.name} button>
                    <ListItemText className="sidebar-item-text">
                      {subItem.label}
                    </ListItemText>
                  </ListItem>
                ))}
              </List>
            ) : null}
          </ListItem>
        ))}
      </List>
    </div>
  )
}

Ve şimdi… işte, bizim göz kamaştırıcı kenar çubuğu bileşeni!

göz kamaştırıcı tepki kenar çubuğu bileşeni olmayabilir

Henüz yakalamadıysanız, bu olumsuzluk istediğimiz kenar çubuğu görünümü başarmak.

Artık kullanıcılarımızın tarayıcılarındaki kapat düğmesine basmalarını ve bir daha web sitemize geri dönmemelerini istemediğimiz için, bunu yalnızca gözler için değil, aynı zamanda kullanıcılar için de daha çekici hale getirmenin bir yolunu bulmamız gerekiyor. DOM ilave olarak.

“Ne demek istiyorsun DOM“, sen sor?

Eh, yakından bakarsanız, bir sorun var! Kullanıcı bir alt öğeye tıklarsa, alt öğeyi oluşturan üst öğe, üst üste bindikleri için tıklama işleyicisini de tüketir! Bu kötü ve kullanıcının deneyimi için bazı kötü, beklenmedik sorunlara yol açar.

yapmamız gereken şey ebeveyni çocuklarından ayırın (alt öğeler) böylece alt öğelerini oluştururlar bitişikböylece fare olayları çakışmaz:

function Sidebar({ items }) {
  return (
    <div className="sidebar">
      <List disablePadding dense>
        {items.map(({ label, name, items: subItems, ...rest }) => (
          <React.Fragment key={name}>
            <ListItem style={{ paddingLeft: 18 }} button {...rest}>
              <ListItemText>{label}</ListItemText>
            </ListItem>
            {Array.isArray(subItems) ? (
              <List disablePadding>
                {subItems.map((subItem) => (
                  <ListItem key={subItem.name} button>
                    <ListItemText className="sidebar-item-text">
                      {subItem.label}
                    </ListItemText>
                  </ListItem>
                ))}
              </List>
            ) : null}
          </React.Fragment>
        ))}
      </List>
    </div>
  )
}

şimdi biz hemen hemen işe devam!

tepki olarak göz kamaştırıcı kenar çubuğu belki

Ekran görüntüsünden, yeni bir sorunumuz var gibi görünüyor: alt öğeler, üst düzey öğelerden garip bir şekilde daha büyük. Hangilerinin alt, hangilerinin üst seviye olduğunu tespit etmenin bir yolunu bulmalıyız.

Bunu kodlayabilir ve bir gün olarak adlandırabiliriz:

function Sidebar({ items }) {
  return (
    <div className="sidebar">
      <List disablePadding dense>
        {items.map(({ label, name, items: subItems, ...rest }) => {
          return (
            <React.Fragment key={name}>
              <ListItem style={{ paddingLeft: 18 }} button {...rest}>
                <ListItemText>{label}</ListItemText>
              </ListItem>
              {Array.isArray(subItems) ? (
                <List disablePadding dense>
                  {subItems.map((subItem) => {
                    return (
                      <ListItem
                        key={subItem.name}
                        style={{ paddingLeft: 36 }}
                        button
                        dense
                      >
                        <ListItemText>
                          <span className="sidebar-subitem-text">
                            {subItem.label}
                          </span>
                        </ListItemText>
                      </ListItem>
                    )
                  })}
                </List>
              ) : null}
            </React.Fragment>
          )
        })}
      </List>
    </div>
  )
}
.sidebar-subitem-text {
  font-size: 0.8rem;
}

Ancak kenar çubuğu bileşenimizin dinamik olması gerekiyor. İdeal olarak, öğelerini arayandan sahne olarak iletilen öğelere göre oluşturmasını istiyoruz.

Basit bir kullanacağız depth kenar çubuğu öğelerinin kullanacağını ve derinliğe bağlı olarak kendi boşluklarını buna göre ayarlayabileceklerini destekleyin. depth Ağacın ne kadar aşağısında olurlarsa olsunlar. Ayrıca, durum mantığını tanıtarak karmaşıklaştırmadan derinliği artırabilmemiz için kenar çubuğu öğesini kendi bileşenine çıkaracağız.

İşte kod:

function SidebarItem({ label, items, depthStep = 10, depth = 0, ...rest }) {
  return (
    <>
      <ListItem button dense {...rest}>
        <ListItemText style={{ paddingLeft: depth * depthStep }}>
          <span>{label}</span>
        </ListItemText>
      </ListItem>
      {Array.isArray(items) ? (
        <List disablePadding dense>
          {items.map((subItem) => (
            <SidebarItem
              key={subItem.name}
              depth={depth + 1}
              depthStep={depthStep}
              {...subItem}
            />
          ))}
        </List>
      ) : null}
    </>
  )
}

function Sidebar({ items, depthStep, depth }) {
  return (
    <div className="sidebar">
      <List disablePadding dense>
        {items.map((sidebarItem, index) => (
          <SidebarItem
            key={`${sidebarItem.name}${index}`}
            depthStep={depthStep}
            depth={depth}
            {...sidebarItem}
          />
        ))}
      </List>
    </div>
  )
}

Peki burada neler oluyor?

Kenar çubuğu ön işleme aşamasını yapılandırmak için bazı güçlü aksesuarlar açıkladık, örneğin: depth ve depthStep. SidebarItem kendi bileşenine çıkarıldı ve kullandığı oluşturma bloğunun içinde depth aralığını hesaplamak için. daha yüksek depth içinde bulundukları ağacın daha derinlerindedir.

Bu satır nedeniyle hepsi mümkün:

{
  items.map((subItem) => (
    <SidebarItem
      key={subItem.name}
      depth={depth + 1}
      depthStep={depthStep}
      {...subItem}
    />
  ))
}

depth tarafından artırılır 1 her seferinde yeni bir alt öğe listesi daha derine iner.

Ve özyineleme içinde var SidebarItem çünkü artık bir şey kalmayana kadar kendini çağırıyor temel durumbaşka bir deyişle, dizi boş olduğunda bu kod parçası otomatik olarak durur:

{
  items.map((subItem) => (
    <SidebarItem
      key={subItem.name}
      depth={depth + 1}
      depthStep={depthStep}
      {...subItem}
    />
  ))
}

Şimdi özyinelemeli kenar çubuğu bileşenini test edelim:

kaynak/App.js

const items = [
  { name: 'home', label: 'Home' },
  {
    name: 'billing',
    label: 'Billing',
    items: [
      { name: 'statements', label: 'Statements' },
      { name: 'reports', label: 'Reports' },
    ],
  },
  {
    name: 'settings',
    label: 'Settings',
    items: [
      { name: 'profile', label: 'Profile' },
      { name: 'insurance', label: 'Insurance' },
      {
        name: 'notifications',
        label: 'Notifications',
        items: [
          { name: 'email', label: 'Email' },
          {
            name: 'desktop',
            label: 'Desktop',
            items: [
              { name: 'schedule', label: 'Schedule' },
              { name: 'frequency', label: 'Frequency' },
            ],
          },
          { name: 'sms', label: 'SMS' },
        ],
      },
    ],
  },
]

function App() {
  return (
    <div>
      <Sidebar items={items} />
    </div>
  )
}

Tepkide göz kamaştırıcı kenar çubuğu özyinelemeli

Ve işte bizde!

ile oynayalım depthStep biraz ve daha yüksek bir değere geçin:

function App() {
  return (
    <div>
      <Sidebar items={items} />
    </div>
  )
}

Recursionized # 2'de göz kamaştırıcı kenar çubuğu

Çözüm

İsteğe bağlı olarak repoyu adresinden indirebilirsiniz. github bağlantısı ve kenar çubuğunun ek özelliklerine bakın. Oluşturmada ek bir katman eklemek gibi daha süslü işlevlere sahiptir (kenar çubuğu bölümler) yol açan (bölücüler) ayırıcılar, kenar çubuğu genişletme/daraltma, simgeler vb.

Umarım bunu değerli bulmuşsunuzdur ve gelecekte daha fazlasını ararsınız!

Bir cevap yazın

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