Päänsä luultavasti on kaksi pääajattelua, kun luet tätä johdantoa:
Mutta odota! Siinä olet väärässä - ja todistan sen sinulle. Jos olet valmis sijoittamaan 10 minuuttia ajastasi, näytän sinulle, kuinka ClojureScript voi tehdä käyttöliittymien ja React-y-sovellusten kirjoittamisesta hauskaa, nopeaa ja - mikä tärkeintä - toimiva .
Joten sinulla ei ole paljon aikaa oppia ClojureScriptia, ja haluat vain nähdä, mihin koko asia on menossa. Ensinnäkin, mikä on ClojureScript?
ClojureScript-verkkosivustolta: ClojureScript on Clojuren kääntäjä, joka kohdistuu JavaScriptiin. Se lähettää JavaScript-koodia, joka on yhteensopiva Google Closure -optimoivan kääntäjän edistyneen kääntötilan kanssa.
ClojureScriptillä on paljon tarjottavaa muun muassa:
Kun tämä on poissa, avataan tämä matojen tölkki esimerkillä:
(defn component [] [:div 'Hello, world!'])
Huomautus niille, jotka eivät tunne Lisp-murteita tai ClojureScript: Tämän esimerkin tärkeimmät osat ovat :div
, []
ja ()
:div
on elementtiä edustava avainsana. []
on vektori, aivan kuten ArrayList
Java-sovelluksessa ja ()
on sekvenssi, aivan kuten a LinkedList
. Kosken tätä tarkemmin myöhemmin tässä viestissä!
Tämä on ClojureScriptin React-komponentin perusmuoto. Siinä se - vain avainsana, merkkijono ja koko joukko luetteloita.
Pshaw! sanot, että se ei poikkea merkittävästi JSX: n tai TSX: n 'hei maailma' -kohdasta:
function component() { return ( 'Hello, world!' ); }
On kuitenkin joitain ratkaisevia eroja, jotka voimme havaita jopa tästä perusesimerkistä:
Näillä kahdella pienellä erolla on valtavat seuraukset, ei vain siinä, miten sinä kirjoittaa koodi, mutta miten ilmaisette itseänne myös!
Kuinka voit, kysyt? Hypätään taisteluun ja katsotaan, mitä muuta ClojureScript on meille varannut ...
Liittyvät:Tämän ClojureScript-opetusohjelman aikana yritän olla kaivamatta liian syvälle siihen, mikä tekee Clojuresta [Script] suurenmoisen (mikä on paljon asioita, mutta poikkeaen). Siitä huolimatta on hyödyllistä käsitellä joitain peruskäsitteitä, jotta on mahdollista ymmärtää, mitä voimme tehdä täällä.
Niille kokeneille clojuristeille ja lispialaisille voit siirtyä eteenpäin seuraavaan osioon!
Ensin on käsiteltävä kolme pääkäsitettä:
Clojure [Script] -käsitteellä on avainsana. Se on jossakin vakion merkkijonon (esimerkiksi Java) ja avaimen välissä. He ovat symboliset tunnisteet, jotka arvioivat itselleen .
Esimerkiksi avainsana :cat
viittaa aina :cat
eikä koskaan mihinkään muuhun. Aivan kuten Javassa saatat sanoa:
private static const String MY_KEY = 'my_key'; // ... myMap.put(MY_KEY, thing); // ... myMap.get(MY_KEY);
… Clojuressa sinulla olisi yksinkertaisesti:
(assoc my-map :my-key thing) (my-map :my-key) ; equivalent to (:my-key my-map) ...nice and flexible!
Huomaa myös: Clojuressa kartta on sekä kokoelma (arvojen avaimet, aivan kuten Java HashMap
), että toiminto sen sisällön käyttämiseen. Siisti!
Clojure [Script] on Lisp-murre tarkoittaa, että se painottaa paljon luetteloita. Kuten aiemmin mainitsin, on kaksi pääasiaa, joista on oltava tietoinen:
[]
on vektori, aivan kuten ArrayList
.()
on sekvenssi, aivan kuten a LinkedList
.Voit luoda luettelon asioista Clojuressa [Script] seuraavasti:
[1 2 3 4] ['hello' 'world'] ['my' 'list' 'contains' 10 'things'] ; you can mix and match types ; in Clojure lists!
Sekvensseissä se on hieman erilainen:
'(1 2 3 4) '('hello' 'world')
Valmisteleva '
selitetään seuraavassa osassa.
Lopuksi meillä on toimintoja. Clojure [Script] -funktio on a järjestys se kirjoitetaan ilman valmistelua '
. Luettelon ensimmäinen elementti on itse funktio, ja kaikki seuraavat elementit ovat argumentteja . Esimerkiksi:
(+ 1 2 3 4) ; -> 10 (str 'hello' ' ' 'world') ; -> 'hello world' (println 'hi!') ; prints 'hi!' to the console (run-my-function) ; runs the function named `run-my-function`
Yksi tämän käytöksen seurauksista on, että voit rakentaa funktion määritelmän suorittamatta sitä! Vain ”alasti” jakso suoritetaan, kun ohjelmaa arvioidaan.
(+ 1 1) ; -> 2 '(+ 1 1); -> a list of a function and two numbers
Tästä tulee merkitystä myöhemmin!
Toiminnot voidaan määritellä muutamalla tavalla:
; A normal function definition, assigning the function ; to the symbol `my-function` (defn my-function [arg1 arg2] (+ arg1 arg2)) ; An anonymous function that does the same thing as the above (fn [arg1 arg2] (+ arg1 arg2)) ; Another, more concise variation of the above #(+ %1 %2)
Joten nyt kun olemme käsitelleet perusasiat, perehdytään hieman yksityiskohtaisemmin nähdäksesi, mitä täällä tapahtuu.
Reagoi ClojureScript-ohjelmassa tapahtuu yleensä kirjastolla nimeltä Reagenssi . Reagenssi käyttää Hiccupia ja sen syntaksia HTML: n esittämiseen. Alkaen Hikka-repo Wiki:
'Hikka kääntää Clojure-tietorakenteet näin:'
[:a {:href 'http://github.com'} 'GitHub']
'HTML-merkkijonoihin näin:'
GitHub
Yksinkertaisesti sanottuna ensimmäinen elementti luettelosta tulee HTML-elementtityyppi, ja lopusta tulee kyseisen elementin sisältö. Vaihtoehtoisesti voit antaa kartan määritteistä, jotka liitetään sitten kyseiseen elementtiin.
Elementit voidaan sijoittaa toisiinsa yksinkertaisesti sijoittamalla ne vanhempiensa luetteloon! Tämä on helpoin nähdä esimerkillä:
[:div [:h1 'This is a header'] [:p 'And in the next element we have 1 + 1'] [:p (+ 1 1)]]
Huomaa, kuinka voimme laittaa minkä tahansa vanhan funktion tai yleisen Clojure-syntaksin rakenteeseen ilman, että meidän on erikseen ilmoitettava upotusmenetelmää. Se on loppujen lopuksi vain luettelo!
Ja vielä parempi, mitä tämä arvioi ajon aikana?
[:div [:h1 'This is a header'] [:p 'And in the next element we have 1 + 1'] [:p 2]]
Tietysti luettelo avainsanoista ja sisällöstä! Ei ole hauskoja tyyppejä, ei maagisia piilotettuja menetelmiä. Se on vain tavallinen vanha luettelo asioista. Voit liittää ja pelata tällä listalla niin paljon kuin haluat - mitä näet on mitä saat.
Kun Hiccup tekee asettelun ja Reagentti tekee logiikan ja tapahtumien käsittelyn, tuloksena on täysin toimiva React-ympäristö.
Selvä, sidotaan tämä yhteen enemmän joillakin komponenteilla. Yksi Reactin (ja Reagentin) maagisista asioista on se, että jaat näkymän ja asettelulogiikan moduuleiksi, joita voit sitten käyttää uudelleen koko sovelluksessasi.
Oletetaan, että luomme yksinkertaisen komponentin, joka näyttää painikkeen ja yksinkertaisen logiikan:
; widget.cljs (defn component [polite?] [:div [:p (str 'Do not press the button' (when polite? ', please.'))] [:input {:type 'button' :value 'PUSH ME' :on-click #(js/alert 'What did I tell you?')}]])
Nopea huomautus nimeämisestä: Clojuren moduulit ovat yleensä nimialueita, joten widget.cljs
voidaan tuoda nimitilassa widget
. Tämä tarkoittaa, että ylätaso component
toimintoa käytetään nimellä widget/component
. Haluan, että moduuleja kohden on vain yksi ylätason komponentti, mutta tämä on tyyliasetus - saatat haluta nimetä komponenttitoimintosi esimerkiksi polite-component
tai widget-component
.
Tämä yksinkertainen komponentti antaa meille valinnaisen kohtelevan widgetin. (when polite? ', please.')
arvioi arvoksi ', please.'
kun polite? == true
ja nil
kun se on false
.
Upotetaan tämä nyt app.cljs
:
(defn app [] [:div [:h1 'Welcome to my app'] [widget/component true]])
Tässä upotamme widgetimme sovelluskomponenttiin kutsumalla sitä luettelon ensimmäiseksi kohteeksi - aivan kuten HTML-avainsanat! Voimme sitten siirtää kaikki lapset tai parametrit komponentille toimittamalla ne muihin saman luettelon elementteihin. Täällä ohitamme yksinkertaisesti true
, siis widgetissämme polite? == true
, ja näin saamme kohteliaan version.
Jos arvioisimme sovellustoimintamme nyt, saisimme seuraavan:
[:div [:h1 'Welcome to my app'] [widget/component true]] ; <- widget/component would look more like a ; function reference, but I have kept it ; clean for legibility.
Huomaa kuinka widget/component
ei ole arvioitu! (Katso Toiminnot-osiossa jos olet hämmentynyt.)
DOM-puusi komponentit arvioidaan (ja muunnetaan siten todellisiksi React-kohteiksi kulissien takana) vain, jos ne on päivitetty, mikä pitää asiat mukavina ja röyhkeinä ja vähentää monimutkaisuutta, jota sinun on käsiteltävä milloin tahansa.
Lisätietoja aiheesta saat asiasta kiinnostuneille julkaisussa Reagent docs .
Huomaa lisäksi, kuinka DOM on vain luetteloluettelo, ja komponentit ovat vain toimintoja, jotka palauttavat luetteloluetteloita. Miksi tämä on niin tärkeää, kun opit ClojureScriptiä?
Koska mitä tahansa voit tehdä toiminnoille tai luetteloille, voit tehdä komponenteille.
Täältä voit saada yhdistettyjä tuottoja käyttämällä Lisp-murretta, kuten ClojureScript: Komponenteistasi ja HTML-elementeistäsi tulee ensiluokkaisia objekteja, joita voit käsitellä kuten mitä tahansa muuta normaalia tietoa! Haluan sanoa vain uudestaan:
Komponentit ja HTML-elementit ovat ensimmäisen luokan tuettuja objekteja Clojure-kielellä!
Aivan, kuulit minut. Se on melkein kuin Lisps on suunniteltu käsittelemään luetteloita (vihje: ne olivat.)
Tämä sisältää esimerkiksi:
(def words ['green' 'eggs' 'and' 'ham']) (defn li-shout [x] [:li (string/uppercase x)) (concat [:ol] (map li-shout words) ; becomes [:ol [:li 'GREEN'] [:li 'EGGS'] [:li 'AND'] [:li 'HAM']]
; in widget.cljs (defn greeting-component [name] [:div [:p (str 'Hiya ' name '!')]]) ; ... (def shouty-greeting-component #(widget/greeting-component (string/uppercase %))) (defn app [] [:div [:h1 'My App'] [shouty-greeting-component 'Luke']]) ; <- will show Hiya LUKE!
(def default-btn-attrs {:type 'button' :value 'I am a button' :class 'my-button-class'}) (defn two-button-component [] [:div [:input (assoc default-btn-attrs :on-click #(println 'I do one thing'))] [:input (assoc default-btn-attrs :on-click #(println 'I do a different thing'))]])
Tavallisten vanhojen tietotyyppien, kuten luetteloiden ja karttojen, käsittely on dramaattisesti yksinkertaisempaa kuin mikä tahansa luokkaan muistuttava, ja loppujen lopuksi se on paljon tehokkaampaa pitkällä aikavälillä!
Okei, tehdään lyhyesti. Mitä ClojureScript-opetusohjelma on tähän mennessä osoittanut?
Nämä kaksi kohtaa sopivat tiukasti Clojure- ja toiminnalliseen ohjelmointietokseen - koodi on tiedot manipuloida, ja monimutkaisuus rakentuu yhdistämällä vähemmän monimutkaisia osia. Esitämme ohjelmamme (verkkosivumme tässä esimerkissä) datana (luettelot, toiminnot, kartat) ja pidämme sitä sillä tavalla viimeiseen hetkeen asti, jolloin Reagent ottaa haltuunsa ja muuttaa sen React-koodiksi. Tämä tekee koodistamme uudelleenkäytettävän, ja mikä tärkeintä, erittäin helppo lukea ja ymmärtää hyvin pienellä taikalla.
Nyt osaamme tehdä sovelluksen, jolla on joitain perustoimintoja, joten siirrymme eteenpäin siihen, miten voimme tehdä siitä hyvän. On olemassa muutama tapa lähestyä tätä, yksinkertaisin tapa olla tyylitaulukoiden avulla ja viitata niiden luokkiin komponentteissasi:
.my-class { color: red; }
[:div {:class 'my-class'} 'Hello, world!']
Tämä toimii täsmälleen kuten voit odottaa, esittäen meille kauniin, punaisen 'Hei, maailma!' teksti.
Miksi kuitenkin mennä kaikkiin näihin ongelmiin jakamalla näkymä ja logiikkakoodi komponentteihisi, mutta sitten erottamalla muotoilusi tyylitaulukoksi - sinun ei tarvitse vain etsiä kahta eri paikkaa, mutta olet tekemisissä kahden erilaisen kanssa myös kielillä!
Miksi et kirjoittaisi CSS: ää nimellä koodi komponentteihimme (katso teema täältä?). Tämä antaa meille joukon etuja:
Oma suosikki makuni CSS-in-koodissa on Clojure-tyylitaulukot (cljss) . Upotettu CSS näyttää seuraavalta:
;; -- STYLES ------------------------------------------------------------ (defstyles component-style [] {:color 'red' :width '100%'}) ;; -- VIEW -------------------------------------------------------------- (defn component [] [:div {:class (component-style)} 'Hello, world!'])
defstyles
luo toiminnon, joka luo meille yksilöllisen luokan nimen (mikä sopii kaikille, jotka tuovat komponentteja.)
Cljs: t voivat tehdä sinulle monia muita asioita (säveltäminen tyylit, animaatiot, elementtien ohitukset jne.), Joita en käsittele tässä yksityiskohtaisesti. Suosittelen, että tarkistat sen itse!
Viimeiseksi on liima, jota tarvitaan tämän kaiken kiinnittämiseen yhteen. Onneksi projektitiedoston ja index.html
: n lisäksi kattilalevy on tässä minimissä.
Tarvitset:
project.clj
. Jokaisen Clojure-projektin peruselementti määrittelee riippuvuutesi - jopa suoraan GitHubista —Ja muut rakennusominaisuudet (samanlainen kuin build.gradle
tai package.json
.)index.html
joka toimii sitovana pisteenä Reagenssi-sovelluksessa.Löydät tämän ClojureScript-opetusohjelman täydellisen koodiesimerkin saatavilla GitHubissa .
Joten se on (toistaiseksi). Toivottavasti olen ainakin herättänyt uteliaisuutesi pieneen määrään, oli se sitten Lisp-murre (Clojure [Script] tai muuten) tai jopa kokeilla itseäsi oman Reagent-sovelluksen luomisessa! Lupaan teille, ettet tule katumaan sitä.
Liity kanssani tämän artikkelin seurantaan, Osavaltioon pääseminen , jossa puhun valtionhallinnosta kehys uudelleen - tervehdi Reduxia ClojureScriptissä!
React on Java-käyttöliittymän kehityskehys.
ClojureScript on Clojuren kääntäjä, joka kohdistuu JavaScriptiin. Se lähettää JavaScript-koodia, joka on yhteensopiva Google Closure -optimoivan kääntäjän edistyneen kääntötilan kanssa. Se perii suurimman osan interaktiivista kehitystä tukevasta dynaamisesta ohjelmointikielestä Clojure.
Lisp on nimi kieliryhmälle, jolla on yhteisiä piirteitä (kuten Clojure, Common Lisp, Scheme jne.), Joten itse 'Lisp' ei ole kirjoitettu. (Tämä on kuin kysytään 'Mitkä ovat kakun ainesosat?' Useimmat kakut seuraavat samanlaista teemaa, mutta niillä on erilaisia ainesosia.)
Joo! Lisp priorisoi 'koodin datana' -periaatetta. Tämä voidaan nähdä itse nimen johdosta - LISt-prosessori. Lisp-murteessa kaikki on dataa - jopa funktiokutsut ovat luettelo argumenteista! Lisp on fantastinen ohjelmointikielityyli - on olemassa monia erilaisia makuja mihin tahansa tarpeeseen.
Lisp-murteet käyttävät tavallisesti osia toiminnallisista ja välttämättömistä ohjelmointikielistä. Clojure ja ClojureScript ovat multiparadigmia - ne tukeutuvat voimakkaasti toiminnalliseen ohjelmointiin ja antavat sinun haarautua välttämättömäksi, kun sitä tarvitaan. Näin voit kokea molempien maailmojen parhaat puolet!
Google Closure Library on laaja ja vakiintunut selainten välinen JavaScript-kirjasto, joka sisältää erilaisia työkaluja käyttöliittymän, DOM: n manipulointiin, palvelinviestintään, testaamiseen jne. Se on tarkoitettu käytettäväksi Google Closure Compilerin kanssa.
Google Closure Compiler kokoaa JavaScriptin paremmaksi JavaScriptiksi manipuloimalla, optimoimalla ja minimoimalla sen varmistamiseksi, että se latautuu ja toimii nopeammin. Lisäksi se suorittaa joukon tarkistuksia koodillesi ongelmien minimoimiseksi ajon aikana.