Sisältö: Piilotetut asiakirjat

Vastuuvapauslauseke: Tämä artikkeli koskee Angularia, toisin kuin AngularJS. Tämä tarkoittaa sitä, että se koskee kulma 2.x, 4.x ja toivottavasti tulevia versioita.

Jos olet joskus yrittänyt kirjoittaa uudelleenkäytettävää osaa kulmaan, joudut todennäköisesti projisoimaan sisältö sen sisälle. Löysit , löysit siitä muutaman blogiviestin ja sait komponentin toimimaan. Tämä artikkeli opastaa sisällön projisointia ja edistyneitä käyttötapoja vastatakseen kysymyksiin, jotka ilmestyvät jatkuvasti Clarity-tiimissä ja ilmeisesti myös Angularin GitHub-arkistossa.

Tavallisesti aloitan tämän artikkelin osoittamalla teille kuvailemasi ominaisuuden viralliset asiakirjat, mutta sisältöprojektiota varten sitä ei vielä ole… Joten hyppäämme sisään!

Yksinkertainen esimerkki

Käytämme tässä artikkelissa yhtä esimerkkiä, joka näyttää erilaisia ​​tapoja suunnitella sisältöä ja erilaisia ​​reunatapauksia. Koska monet kysymykset liittyvät komponentin elinkaareen kulmassa, pääkomponentillamme on laskuri, joka näyttää kuinka monta kertaa se on toteutettu:

Käytämme tätä Counter-komponenttia ja projisoimme sen millä tahansa tavalla voimme ajatella osaksi tämän Wrapper-komponentin muunnelmaa, joka vain projisoi sen tyyliseen laatikkoon:

Tarkistetaan vain nämä työt odotetulla tavalla asettamalla kolme laskuria kääreen sisälle:

Se näyttää 1, 2 ja 3 odotetusti. Toistaiseksi niin hyvä.

Tästä eteenpäin testaamme yksinkertaisuus yksinkertaisella laskurilla. Joten oletussovelluksemme HTML jatkaa eteenpäin:

Kohdennettu projektio

Joskus haluat, että kääreesi erilaiset lapset heijastuvat mallin eri osiin. Tämän käsittelemiseksi tukee valittua ominaisuutta, jonka avulla voit projisoida tiettyä sisältöä tietyissä paikoissa. Tämä ominaisuus vie CSS-valitsimen (oma elementti,. Oma luokka, [oma ominaisuus],…) vastaamaan haluamiasi lapsia. Jos sisällytät ng-sisällön ilman valittua attribuuttia, se toimii kaikessa ja vastaanottaa kaikki lapset, jotka eivät vastanneet mitään muuta ng-sisältöelementtiä. Tiivistettynä:

Laskuri on oikein projisoitu toiseen, siniseen ruutuun, kun taas lapsi, joka ei ole laskuri, päätyy punaiseen laatikkoon. Huomaa, että kohdennettu ng-sisältö on etusijalla kokonaisuuteen nähden, vaikka se olisi mallipohjan jälkeen.

ngProjectAs

Joskus sisäinen komponentti on piilotettu toiseen suurempaan komponenttiin. Joskus sinun täytyy vain kääriä se ylimääräiseen säilytysastiaan käyttääksesi ngIf tai ngSwitch. Mistä tahansa syystä usein tapahtuu, että sisäinen komponentti ei ole kääreen suora lapsi. Kääritämme laskurikomponentti -osaan simuloidaksesi sitä ja katso mitä tapahtuu kohdeprojektiollemme:

Laskurikomponentti projisoidaan nyt punaiseksi kaikkiin-elementtiin, koska sen ympärillä oleva ng-säilö ei enää vastaa select = "laskuria". Tämän korjaamiseksi meidän on käytettävä ngProjectAs-määritettä, joka voidaan laittaa ehdottomasti mille tahansa elementille ja antaa sen "naamioida" minkä tahansa elementin sisällön projisointitarkoituksiin. Se vie täsmälleen saman tyyppiset valitsimet kuin -valintaattribuutti.

Joten pitämällä kääremme samalla tavalla kuin ennen (sinisellä ja punaisella ruudulla), voimme nyt käyttää tätä uutta ominaisuutta sovelluksessamme:

Tiski on taas sinisessä laatikossa, aivan kuten halusimme.

Aika nakata ja tuottaa

Ok, saimme yksinkertaisemmat tapaukset toimimaan. Mutta mitä tapahtuu, jos ajattelemme ruudun ulkopuolella (silmänräpäs)? Aloitetaan yksinkertaisella kokeilulla: laita malliimme kaksi lohkoa ilman valitsimia. Mitä pitäisi tapahtua? Meillä on kaksi laskuria vai vain yksi? Jos päädymme kahteen, näytetäänkö niissä 1 ja 1 vai 1 ja 2?

Vastaus on, että meillä on yksi laskuri viimeisessä , toinen on tyhjä! Kokeillaan vähän enemmän, ennen kuin yritämme selittää miksi. Olemme pääsemässä esimerkkiin, joka herätti eniten kysymyksiä GitHubista: entä jos kääritän * ngIf: iin?

Ensi silmäyksellä se näyttää toimivan hyvin. Mutta jos kytket sen päälle ja pois painikkeella, huomaat, että laskuri ei kasva. Tämä tarkoittaa, että laskurikomponentimme on hetkellinen - ei koskaan tuhota eikä luoda uudelleen. Eikö se ole päinvastainen siihen, mitä * ngIf on tarkoitus tehdä? Katsotaanpa * ngFor: lla, onko meillä sama ongelma:

Sama asia kuin useassa -tapauksessa, vain viimeinen saa laskurin! Miksi se ei toimi odotetulla tavalla?

Selitys

ei "tuota" sisältöä, se vain projisoi olemassa olevan sisällön. Ajattele sitä jonkin muunnoksena solmua.appendChild (el) tai tunnettua JQuery-versiota $ (solmu) .append (el): Näillä menetelmillä solmua ei kloonata, se vain siirretään uuteen sijaintiin. Tämän vuoksi heijastetun sisällön elinkaari on sidottu mihin se on ilmoitettu, ei mihin se näytetään.

Tähän käyttäytymiseen on kaksi syytä: odotusten ja suorituskyvyn johdonmukaisuus. ”Odotusten johdonmukaisuus” tarkoittaa sitä, että kehittäjänä voin lukea sovellukseni koodin ja arvata sen käyttäytymisen kirjoittamani koodin perusteella. Oletetaan, että kirjoitin tämän koodin:

Ilmeisesti laskuri tulee hetkeksi hetkeksi. Mutta nyt, sanotaanpa staattisen kääreen sijasta, käytän sellaista kolmannen osapuolen kirjastosta:

Jos kolmannen osapuolen kirjastolla olisi kyky hallita laskuri elinkaarta, minulla ei olisi mitään keinoa tietää, kuinka monta kertaa se on toteutettu. Ainoa tapa tietä minun olisi tarkastella kolmannen osapuolen kirjaston koodeja ja olla niiden tekemien sisäisten muutosten armoilla. Elinkaarin pakottaminen sitoutumaan sovelluskomponenttiini kääreen sijasta tarkoittaa, että voin turvallisesti olettaa, että laskuri välitetään yhden kerran, tietämättä mitään kolmannen osapuolen kirjaston todellisesta koodista.

Esitysosa on paljon ilmeisempi. Koska ng-sisältö siirtää vain elementtejä, se voidaan tehdä kokoontumisaikana kuin ajoaikana, mikä vähentää merkittävästi varsinaisen sovelluksen työtä (varsinkin kun käännetään etukäteen, jota kulma-cli tekee oletuksena).

Ratkaisu

Jotta kääre voi hallita lastensa välitystä, meidän on annettava sille malli sisällölle kuin itse sisällölle. Tämä voidaan tehdä kahdella tavalla: käyttämällä -elementtiä sisällön ympärillä tai käyttämällä rakennedirektiiviä “tähden” syntaksin kanssa, kuten * myContent. Käytämme yksinkertaisuuden vuoksi esimerkeissämme -sintaksia, mutta täältä löydät kaikki tarvitsemasi tähdetunnuksen. Uusi sovelluksemme näyttää tältä:

Kääre ei voi enää käyttää , koska se vastaanottaa mallin. Sen on käytettävä mallia @ContentChild-sovelluksen kanssa ja näytettävä se ngTemplateOutlet-sovelluksella:

Tiskimme on nyt kasvanut oikein joka kerta, kun piilotamme sen ja osoitamme sen uudestaan! Yritetään nyt uudelleen * ngFor:

Yksi laskuri jokaisessa laatikossa, näyttäen 1, 2 ja 3. Tarkalleen mitä etsimme!

Toivottavasti nämä selitykset sisältyvät pian itse kulma-aineistoon, mutta toivon, että tällä välin syvälle -ongelmalle on vastattu suurimpaan osaan kysymyksistänne. Erityisesti se selittää, miksi kulmikirjastot pyytävät malleja niin usein kuin vain projisoivia malleja. Se tekee sovellusliittymästä hieman sanallisemman, mutta avaa heille paljon enemmän mahdollisuuksia: välilehtien sisällön laiska lataaminen, nimikkeiden kopioiminen komponentin eri paikoissa jne.

Jos olet utelias ja tunnet olevani hullun tiedemiehen päivä, mene eteenpäin ja kokeile edistyneempiä kokeita, kuten esimerkiksi sisällön projisointia . Tulokset ovat kaikki yhdenmukaisia ​​edellisen selityksen kanssa, mutta joillakin näistä hankalista malleista on hyödyllisiä sovelluksia. Ehkä saamme heidän kanssaan tulevassa blogiviestissä!