Angular'da bir bileşen özel bir direktiftir ve özel özelliği kendi şablonu (html) ve stili (css) olmasıdır. Bu nedenle, bileşenleri kullanmak kodumuzu yüksek derecede ayrılmış, yeniden kullanılabilir ve kolayca genişletilebilir hale getirebilir. Olağan bileşenler aşağıdaki şekilde tanımlanır:
demo.component.ts:
demo.component.html:
demo.component.scss:
Bileşene referans verdiğimizde, bileşenin ayrıştırılmış içeriği şu şekilde görüntülenir:
Bileşenin dışsal olarak projeksiyon edilen içeriği kabul etmesi gerektiğini, yani bileşenin tanımladığından fazlasını sunduğu anlamına gelir. Bu sırada, bu makalenin başkahramanı davet edilmiştirng-içerik。
Basit projeksiyon
En basit olanla başlayalım, değiştirilmiş demo.component.html ve demo.component.scss dosyasını demo.component.html'ye şu şekilde ekleyelim:
demo.component.html:
demo.component.scss:
Etki amaçlılığı için, kabın arka plan rengi kasıtlı olarak turuncu olarak tanımlanmıştır.
Bu noktada, bileşene referans verirken dışarıdan içerik yayınlayabiliriz ve harici içerik turuncu alanda görüntülenir:
Hedefli projeksiyon
Eğer aynı anda birden fazla içerik varsa, dış içerik nasıl yansıtılır?
Önce bir örneme bakalım, ayrım için mavi bir alan, değiştirilmiş demo.component.html ve demo.component.scss ekledim:
demo.component.html:
demo.component.scss:
Bileşene referans vermek için:
Bu noktada, harici içeriğin mavi alana yansıtıldığını göreceğiz:
Tabii ki, turuncu alan kodunu mavi alan kodundan sonra koyarsanız, harici içerik turuncu alana yansıtılır:
Yukarıdaki örnekten, eğer basit bir de varsa, harici içerik bileşen şablonunun son kısmına yansıtılacaktır.
Bu sorunu bildiğimizde, dış içeriği hedefli bir şekilde yansıtabilir miyiz diye merak edebiliriz. Cevap elbette evet.
Bununla başa çıkmak için destek olunseçmekBelirli bir yerde belirli içeriği yansıtmanızı sağlayan özellikler. Bu özellik CSS seçicileri (etiket seçicisi, sınıf seçicisi, öznitelik seçicisi) destekler、... ) istediğiniz gibi davranmak için. ng-içerikte herhangi bir seçme özelliği belirlenmediyse, tam içeriği veya diğer ng-içerik öğeleriyle eşleşmeyen içeriği alır.
Doğrudan örneğe baktığımızda, değiştirilmiş demo.component.html ve demo.component.scss aşağıdaki gibidir:
demo.component.html:
demo.component.scss:
Yukarıdaki koddan da görebileceğiniz gibi, mavi alan etiket başlığının bir kısmını, kırmızı alan div'in "demo2" sınıfındaki kısmını, yeşil alan div'in "demo3" adlı özelliği olan kısmını alacak ve turuncu alan dış içeriğin geri kalanını alacak (start, ben harici embed'in içeriğiyim, son).
Bileşene referans vermek için:
Bu noktada, harici içeriğin belirtilen 'ye yansıtıldığını göreceğiz.
Bilgiyi genişletin
ngProjectAs
Artık ng-content'in select özelliğinin, dış içeriğin belirli bir alana yansıtıldığını belirtmenize olanak tanıdığını biliyoruz.
Select özniteliğine göre içeriği doğru şekilde yansıtmak için bir sınırlama vardır - ister etiket başlığı, ister "demo2" sınıfına sahip bir div ya da "demo3" özellik adına sahip bir div olsun, bu etiketlerin hepsi bileşen etiketinin doğrudan alt düğümleridir.
Doğrudan bir alt düğüm olmasaydı ne olurdu? Demo-bileşen bileşenine referans veren kodu değiştirelim, etiket başlığını bir div'e koyup aşağıdaki gibi değiştirelim:
Bu noktada, içeriğin sekme başlığı kısmının artık mavi alana değil, turuncu alana yansıtıldığını görüyoruz. Bunun nedeni, <ng-content select="header"></ng-content> önceki etiket başlığıyla eşleşmemesi, bu yüzden bu içerik kısmı <ng-content></ng-content> turuncu alana yansıtılır.
Bu problemi çözmek için, herhangi bir elemana uygulanabilen ngProjectAs özelliğini kullanmamız gerekir. Detaylar şunlardır:
ngProjectAs özelliği ayarlandığında, etiket başlığının bulunduğu div select="header"e işaret eder ve etiket başlığının kısmı mavi alana yansıtılır:
<ng-content>İçerik "üretmeyin" Bir deney yapın Bir deney yapmak için önce bir demo-child-bileşen bileşeni tanımlayın:
demo-bileşen bileşeni:
Sonra demo-component içinde demo-child-component için:
Bu noktada, konsolda demo-child-bileşen başlatmanın tamamlandığını görüyoruz! Bu sözler. Ama işlemleri değiştirmek için düğmeye tıkladığımızda, demo-çocuk-bileşen başlatma tamamlanmış oluyor! Artık basılmıyor, yani demo-çocuk bileşenimiz sadece bir kez örnekleniyor - asla yok edilip yeniden yaratılmıyor.
Neden böyle oluyor?
Oluşma nedenleri
<ng-content> İçerik "üretmiyor", sadece mevcut içeriği yansıtıyor. Bunu node.appendChild(el) veya jQuery'deki $(node).append(el) yöntemine eşdeğer olarak düşünebilirsiniz: bu yöntemlerle düğüm klonlanmaz, sadece yeni konumuna taşınır. Bu nedenle, projeksiyon edilen içeriğin yaşam döngüsü, ilan edildiği yere bağlı olacak, yerinde gösterilmeyecek.
Bu aynı zamanda ilkedeki önceki soruyu da açıklar:Eğer aynı anda birden fazla içerik varsa, dış içerik nasıl yansıtılır?
Bu davranış iki nedenle yapılır: tutarlılık ve performans. "İstenen tutarlılık" demek, bir geliştirici olarak uygulamanızın davranışını koduna göre tahmin edebilmenizi ifade eder. Diyelim ki şu kodu yazdım:
Elbette demo-child-component bileşeni bir kez oluşturulacak, ama şimdi üçüncü taraf bir kütüphaneden bir bileşen kullanırsak:
Üçüncü taraf bir kütüphane, demo-çocuk bileşen bileşeninin yaşam döngüsü üzerinde kontrol sahibiyse, kaç kez örneklendiğini bilmenin bir yolu olamaz. Bunu yapmanın tek yolu, üçüncü taraf kütüphanelerin kodlarına bakarak onların iç işlem mantığını anlamak. Bir bileşenin yaşam döngüsünü uygulama bileşenlerimize bağlamanın anlamı, geliştiricilerin sayacların sadece bir kez oluşturulmasını kontrol edebilmesidir; üçüncü taraf kütüphanelerin iç kodunu bilmeden.
Performans nedenleridaha önemli. ng-content sadece hareketli bir eleman olduğundan, bu işlem çalışma zamanında değil, derleme zamanında yapılabilir; bu da gerçek uygulamanın iş yükünü büyük ölçüde azaltır.
Çözüm
Bileşenin projeksiyon alt bileşenlerinin örneklenmesini kontrol edebilmesi için bunu iki şekilde yapabiliriz: <ng-template> içeriğimizin etrafında öğeler ve ngTemplateOutlets kullanarak veya "*" sözdizimiyle yapı direktifleri kullanarak. Basitlik için, örneğinde Sözdizimi <ng-template> kullanacağız.
demo-bileşen bileşeni:
Sonra ng-şablonuna demo-child-component dahil ediyoruz:
Bu noktada, anahtar düğmesine tıkladığımızda, konsol çıktı alıyordemo-çocuk-bileşen başlatma tamamlandı!Bu sözler.
|