Meet Material-UI - uusi suosikki käyttöliittymäkirjasto

Päivitys (17.05.2018): Material-UI v1.0.0 on loppunut! Katso tämä Olivierin viesti.

Häh? Vielä yksi kirjasto? Mitä vikaa Bootstrapissa on? Ja miksi ei v0.20?

Hienoja kysymyksiä! Aloitetaan lyhyellä johdannolla. Lyhyesti sanottuna Material-UI on avoimen lähdekoodin projekti, joka sisältää React-komponentit, jotka toteuttavat Googlen materiaalisuunnittelun.

Se alkoi vuonna 2014, kauan sen jälkeen, kun React tuli yleisöön, ja sen suosio on kasvanut siitä lähtien. Material-UI on yli 35 000 tähteä GitHubissa, ja se on yksi React-palvelun parhaista käyttöliittymäkirjastoista.

Sen menestys ei kuitenkaan tullut ilman haasteita. LESS: llä suunniteltu Material-UI v0.x oli alttiina yleisille CSS-karkoille, kuten globaalille laajuudelle, jotka johtavat projektia CSS-in-JS-reitillä. Näin tapahtui seuraavaksi vuonna 2016.

Matka kohti parempaa tyyliä, kuten Olivier Tassinari totesi, alkoi inline-tyyleillä, mutta niiden optimaalinen suorituskyky ja rajoitettu ominaisuustuki (ajattele pseudon valitsijoita tai mediakyselyjä) saivat joukkueen lopulta siirtymään JSS: ään. Ja poika tekivät he älykkään valinnan.

Mikä on v1-julkaisun hype?

Se on huono perse. Sen lisäksi, että siinä puututaan vähemmistöön liittyviin ongelmiin, se myös avaa loistavia ominaisuuksia, kuten

  • dynaamiset tyylit, jotka on luotu suorituksen aikana
  • sisäkkäisiä teemoja intuitiivisella ohituksella
  • lyhyempi latausaika koodinjaolla

Ja paljon muuta. Kirjasto on myös tarpeeksi kypsä käytettäväksi tuotannossa niin paljon, että tiimi ehdottaa v1: tä kaikille uusille hankkeille.

Okei, aiommeko rakentaa sovelluksen, vai mitä?

Ilo, että kysyit! Tätä demoa varten rakennamme yksinkertaisen kuntosovelluksen. Jokainen on jo kyllästynyt to-do-sovelluksiin jo nyt, eikö niin?

Lukeminen on hienoa ja kaikki, mutta katselu on usein hauskempaa! Katso tämä YouTube-luoma soittolista, jos haluat rakentaa edistyneemmän sovelluksen.

Ok, sinä sai minut vakuuttuneeksi. Kuinka aloitan?

Aloitamme sovelluksemme ensin luo-reagoi -sovelluksella

luo-reagoi-sovellus mui-kunto
cd mui-kunto
koodi.

Entä Material-UI?

Jos sinulla on lankaa, asennus on yhtä helppoa

lanka lisää @ material-ui / core

Muuten npm: llä

npm i @ material-ui / ydin

Viime aikoina määrittelemme @ seuraava tagi vetääksesi viimeisimmän pre-release (esimerkiksi se on saattanut näyttää v1.0.0-beeta.47). Nyt kun sekä v1 että v0.x ovat materiaali-ui-laajuudessa, meidän on viitattava kirjaston ytimeen / core: n kanssa viimeisimmän julkaisun kohdistamiseksi. Älä missaa tätä viimeistä osaa, muuten saat vakaan 0.20-riippuvuuden!

Odota, onko se todella se?

Melkein! Viimeinen asia on fontit. Mennään suositellun Roboto-fontin kanssa Googlen CDN: stä:

Vaihtoehtoisesti voit vetää sen NPM: stä

lanka lisää kirjasin-robotti
# tai npm i typeface-roboto

tällöin sinun täytyy olla tuonti projektisi juuressa

// Varmista kuitenkin, että lataat vain 300, 400 ja 500 kirjasinpainoa!
tuo 'kirjasin-robotti'

Tehty! Mitä teen seuraavaksi?

No, tarkistakaamme App.js-komponentti, ennen kuin jatkamme

Tuo reagoi, {Component} kohdasta 'react'
vie oletusluokan sovellus laajentaa komponenttia {
  tila = {
    harjoitukset: [],
    otsikko: ''
  }
  tehdä () {
    paluu 

Harjoitukset

  } }

Ja miksi et puhdista index.js: tä, kun olemme siinä?

tuo reagoi 'reagoi'
tuo {render} osoitteesta 'react-dom'
Tuo sovellus './App' -sovelluksesta
renderöinti (, document.getElementById ('root'))

Poista jäljellä olevat tiedostot src-tiedostosta, koska me emme tarvitse niitä.

Missä Material-UI tulee?

Tarpeeksi oikeudenmukainen, on aika nähdä se toiminnassa. Muutetaan ruma h1 kauniiksi typografiaotsikkoon:

Tuo typografia kohdasta '@ material-ui / core / Typography'
...
  tehdä () {
    palata (
      
        Harjoitukset
      
    )
  }
}
Huomaa, että versiosta v1.0.0-rc.0 lähtien MUI siirtyi @ material-ui / core: iin ja tuontipolku tasoitettiin. Tämä oli viimeinen rikkova muutos ennakkotiedotteessa.

Mene eteenpäin ja juokse lanka alkamaan nähdä taikuutta.

”Näyttö 1” -kokoinen otsikko, alareunus keskitetty vaakasuoraan

Meillä on hyvä alku! Typografiakomponentissa on ennalta määritetty tyyppikoko. Muita vaihtoehtoja ovat runko1, otsikko, näyttö2 ja niin edelleen. Muiden sisäänrakennettujen rekvisiittien joukossa ovat kohdistus, jota käytämme tässä tekstin keskittämiseen vaakasuoraan, ja gutterBottom, joka lisää alareunan.

Miksi emme laajenna tätä muotoon, jotta voimme luoda omia harjoituksiamme? Aloitamme TextField-kentällä ja sitomme sen tilaotsikon otsikkoon

Tuo typografia kohdasta '@ material-ui / core / Typography'
tuo TextField kentästä '@ material-ui / core / TextField'
...
  handleChange = ({kohde: {nimi, arvo}}) =>
    this.setState ({
      [nimi]: arvo
    })
  tehdä () {
    const {title} = tämä.valtio
    palata (
      ...
      
        
      
    )
  }
}

Tietenkin meidän on tehtävä Reaktista onnelliseksi käärimällä typografia ja muoto vanhemman elementin kanssa. Mikä voisi olla parempi mahdollisuus paperiarkkikortin kaltaiselle taustalle? Katsotaanpa sitten paperille

Tuo paperi '@ material-ui / core / Paper' -kohdasta
...
  tehdä () {
      const {title} = tämä.valtio
      palauta 
        ...
      
    }
  }
}

On myös aika aloittaa nimettyjen tuontien käyttö (olettaen, että Webpack-asetukset mahdollistavat puiden ravistamisen):

Tuo {paperi, typografia, tekstikenttä} tiedostosta '@ material-ui / core'

Makea! Ja mitä hyvää on lomake ilman lähetä-painiketta? Painikkeet ovat niittikomponentti Material-UI: ssä; näet heidät kaikkialla. Esimerkiksi,

tuonti {
  Paperi,
  Typografia,
  Tekstikenttä,
  nappi
} lähteestä "@ material-ui / core"

...

        <-painike
          type = 'Lähetä'
          color = 'ensisijainen'
          variantti = 'esiin'
        >
          Luoda
        
      
    
  }
}

Sen pitäisi lukea hyvin. tyyppi on säännöllinen React-prop, väri ja variantti ovat materiaali-käyttöliittymäkohtaisia ​​ja muodostavat suorakulmion muotoisen painikkeen. Toinen vaihtoehto olisi fab esimerkiksi kelluvalle painikkeelle.

Ei maailman kaunein muoto, mutta saamme sen näyttämään paremmalta hetkessä!

Se ei kuitenkaan tee paljon. Meidän on pysäytettävä lomakkeen lähetystapahtuma

    palauta 
      ...
      
        ...
      
    
  }
}

ja käsittele sitten sitä

  handleCreate = e => {
    e.preventDefault ()
    if (this.state.title) {
      this.setState (({harjoitukset, otsikko}) => ({
        harjoitukset: [
          ...harjoitukset,
          {
            otsikko,
            tunnus: Päivämäärä.nu ()
          }
        ],
        otsikko: ''
      }))
    }
  }

Whoa! Mistä tuo salainen koodi on kyse? Hyvin nopeasti, me

  1. Estä sivun oletuslataus
  2. Tarkista, onko otsikkokenttä tyhjä
  3. Aseta tila päivitystoiminnolla asynk-päivitysten lieventämiseksi
  4. Suoritusharjoitukset ja prevState-objektin otsikko
  5. Levitä seuraavan tilan harjoitukset uudella harjoitusobjektilla
  6. Nollaa otsikko tyhjentääksesi syöttökentän

Arvaa, että minun olisi pitänyt mainita, että olen myös rakastunut ES6: iin. Eivätkö me kaikki ole?

Mutta kuinka me luetteloimme ne?

Nyt on oikea aika. Onko luettelon osaa? Tietenkin, typerä hanhi!

Luettelon sisällä siirrymme harjoitustemme läpi ja palautamme listantemme jokaisella listan listalla

Tuo {List, ListItem, ListItemText} hakemistosta '@ material-ui / core'
...
  tehdä () {
    const {otsikko, harjoitukset} = this.state
    palauta 
      ...
      
        {harjoitukset.kartta (({id, otsikko}) =>
          
            
          
        )}
      
    
  }
}

Koodataan myös muutama alkuharjoitus saadaksesi jotain näytölle. Arvasit sen, kaikkien painonnostoharjoittelujen, naisten ja miesten kolminaisuus:

  tila = {
    harjoitukset: [
      {id: 1, otsikko: 'Bench Press'},
      {id: 2, otsikko: 'Deadlift'},
      {id: 3, otsikko: 'kyykky'
    ],
    otsikko: ''
  }
Voimme nyt luoda ja listata harjoituksemme!

Viimeisenä, mutta ei vähäisimpänä, käyttäjät todennäköisesti tekevät kirjoitusvirheitä, joten lisäämme paremmin poistopainikkeen jokaisen harjoituksen viereen, jotta he voivat poistaa merkinnät, joita he eivät enää halua luettelostaan.

Voimme käyttää ListItemSecondaryActionia tekemään juuri sen. Sijoitettuna luettelon oikeanpuoleiseen reunaan, se voi pitää toissijaista ohjauselementtiä, kuten IconButton jollain toiminnolla

tuonti {
  /*...*/,
  ListItemSecondaryAction,
  IconButton
} lähteestä "@ material-ui / core"
...
          
            
            
               this.handleDelete (id)}
              >
                {/ * ??? * /}
              
            
          
...

Ja älä unohda myös poistonkäsittelyohjelmaa:

  handleDelete = id =>
    this.setState (({harjoitukset}) => ({
      harjoitukset: exercise.filter (ex => ex.id! == id)
    }))

joka suodattaa harjoituksemme harjoituksiin, jotka eivät vastaa poistettavan tunnusta.

Voiko painikkeen sisällä olla roskakorikuvake?

Kyllä, se olisi mahtavaa! Vaikka voisit käyttää Googlen CDN: n materiaalikuvakkeita suoraan joko Icon- tai SvgIcon-komponenttien kanssa, on usein suositeltavaa mennä valmiiden esiasetusten mukana.

Onneksi niille on olemassa Material-UI-paketti

lanka lisää @ material-ui / icons
# tai npm i @ material-ui / icons

Se vie yli 900 virallista materiaalikuvaketta React-komponentteina ja kuvakkeiden nimet ovat melkein identtiset, kuten alla näet.

Oletetaan, että halusimme lisätä roskakorikuvakkeen. Olimme ensin siirtymässä kohtaan material.io/icons saadaksesi selville sen tarkan nimen

Google tarjoaa kaksi variaatiota roskakorikuvakkeista: “Poista” ja “Poista lopullisesti”

Sitten käännämme sen nimen PascalCaseksi tuontipolullamme

Tuo Poista '@ material-ui / icons / Poista'

Aivan kuten Material-UI-komponenttien kanssa, jos asetuksissa on puiden ravistaminen käytössä, voit lyhentää tuontia

Tuo {Poista} tiedostosta @ material-ui / icons

joka on erityisen hyödyllinen, kun tuodaan useita kuvakkeita kerralla.

Nyt kun meillä on roskakorikuvake, näytämme sen Poista-painikkeessamme

 this.handleDelete (id)}>
  
Ja siinä CRUD-sovellus MVP: tämme voidaan pitää valmista!

Kuinka voin tehdä lomakkeesta vähemmän ruma?

Ah, tyyli. Luulin, ettet koskaan kysyisi! CSS: n lempeä kosketus ei vahingoita. Joten sitten tuommeko ulkoinen tyylitaulukko globaaleihin tyyleihin? Tai kenties, käytä CSS-moduuleja ja määritä laajuusluokan nimet elementeillemme? Ei aivan.

Konepellin alla Material-UI haastaa CSS-in-JS-kirjaston, joka tunnetaan nimellä react-jss.

Se on saman kirjoittajan, Oleg Isosen, reagoitu JSS-kirjaston integrointi. Muistatko, että kosketimme sitä alussa? Sen perusajatuksena on antaa sinun määrittää tyylit JavaScriptillä. Mikä tekee JSS: stä erotettavissa muiden libien joukosta, on sen tuki SSR: lle, pieni paketin koko ja rikas plugin-tuki.

Annetaan sille mahdollisuus! Luo sovelluskomponentissamme tyyliobjekti samalla tavalla kuin rivityylien kanssa. Sitten keksiä avain, esimerkiksi juuri, joka viittaa juuripaperi-elementtiin, ja kirjoittaa joitain tyylejä camelCaseen

const tyylit = {
  juuri: {
    marginaali: 20,
    täyte: 20,
    enimmäisleveys: 400
  }
}

Seuraavaksi tuo withStyles HOC materiaalista-ui

tuo {withStyles} tiedostosta '@ material-ui / core / tyylit'

ja kääri sovelluskomponentti siihen, siirtämällä tyyliobjekti argina

vie oletus tyylien kanssa (tyylit) (
  luokan sovellus laajentaa komponenttia {
    ...
  }
)
Huomaa, että voit käyttää myösStyles HOC: ta sisustajana. Muista, että luominen-reagoi-reagoi ei tue koriste-esineitä vielä laatikosta, joten jos vaadit niiden käyttöä, sinun on poistettava tai haarukkaa muokataksesi kokoonpanoa.

Tämä injektoi luokan prop sovellukseen, joka sisältää dynaamisesti luodun luokan nimen juurielementillemme

console.log (this.props) paljastaa luokkaobjektin

Luokan nimen on taattu olevan ainutlaatuinen, ja se lyhennetään usein tuotantorakennuksessa. Sitten määritämme sen paperille className -määritteen avulla

    tehdä () {
      const {otsikko, harjoitukset} = this.state
      const {luokat} = this.props
      palauta 
        ...
      
    }
Paperikomponentti, jossa on käytetty perusmuotoa

Kuinka tämä taikuus toimii? Osoittautuu, withStyles on vastuussa likaisesta työstä. Kulissien takana se injektoi joukon tyylejä DOM: iin