Bagaimana dan di mana menggunakan :: ng-deep?

90

Saya baru mengenal Angular 4, jadi adakah yang bisa menjelaskan bagaimana dan di mana menggunakan ::ng-deepAngular 4?

Sebenarnya saya ingin menimpa beberapa properti CSS pada komponen anak dari komponen induk. Selain itu, apakah itu didukung pada IE11?

Jeyabalan Thavamani
sumber
Karena /deep/dan ::ng-deepkeduanya sudah usang, saya sarankan Anda untuk membaca jawaban ini stackoverflow.com/a/49308475/2275011 dan komentar untuk detail dan solusi lebih lanjut.
Ferie

Jawaban:

92

Biasanya /deep/ “shadow-piercing”kombinator dapat digunakan untuk memaksa gaya turun child components. Selektor ini memiliki alias >>> dan sekarang memiliki alias lain yang disebut :: ng-deep.

karena /deep/ combinatorsudah tidak digunakan lagi, disarankan untuk digunakan::ng-deep

Sebagai contoh:

<div class="overview tab-pane" id="overview" role="tabpanel" [innerHTML]="project?.getContent( 'DETAILS')"></div>

dan css

.overview {
    ::ng-deep {
        p {
            &:last-child {
                margin-bottom: 0;
            }
        }
    }
}

itu akan diterapkan ke komponen anak

Sajeetharan
sumber
Apakah ini mendukung IE11?
Jeyabalan Thavamani
2
Angular melakukan parsing - jadi Anda tidak perlu khawatir tentang kompatibilitasnya.
Simon_Weaver
apakah hanya untuk komponen anak? seperti yang saya ingat dan seperti yang saya lihat di komentar lain, itu juga untuk elemen dom di luar komponen.
yaya
Saya dapat mengonfirmasi bahwa itu melakukan komponen induk juga ... Baru saja menangani kasus itu dan merasa terganggu olehnya.
Shadoweb
1
Luar biasa, ini bekerja dengan sempurna.
Alfredo Zamudio
70

PEMAKAIAN

::ng-deep, >>>dan /deep/menonaktifkan enkapsulasi tampilan untuk aturan CSS tertentu, dengan kata lain, ini memberi Anda akses ke elemen DOM, yang tidak ada di HTML komponen Anda. Misalnya, jika Anda menggunakan Angular Material (atau pustaka pihak ketiga lainnya seperti ini), beberapa elemen yang dihasilkan berada di luar area komponen Anda (seperti dialog ) dan Anda tidak dapat mengakses elemen tersebut secara langsung atau menggunakan CSS biasa cara. Jika Anda ingin mengubah gaya elemen tersebut, Anda dapat menggunakan salah satu dari tiga hal tersebut, misalnya:

::ng-deep .mat-dialog {
  /* styles here */
}

Untuk saat ini tim Angular merekomendasikan membuat manipulasi "dalam" hanya dengan enkapsulasi tampilan TEREMULASI .

BANTAHAN

Manipulasi "dalam" sebenarnya juga tidak digunakan lagi , TETAPI masih berfungsi untuk saat ini, karena Angular melakukan dukungan pra-pemrosesan (jangan terburu-buru untuk menolak ::ng-deephari ini, lihat praktik penghentian terlebih dahulu).

Bagaimanapun, sebelum mengikuti cara ini, saya sarankan Anda untuk melihat cara menonaktifkan pendekatan enkapsulasi tampilan (yang juga tidak ideal, ini memungkinkan gaya Anda bocor ke komponen lain), tetapi dalam beberapa kasus, ini cara yang lebih baik. Jika Anda memutuskan untuk menonaktifkan enkapsulasi tampilan, sangat disarankan untuk menggunakan kelas tertentu untuk menghindari perpotongan aturan CSS, dan terakhir, hindari kekacauan di lembar gaya Anda. Sangat mudah untuk menonaktifkannya langsung di file komponen .ts:

@Component({
  selector: '',
  template: '',
  styles: [''],
  encapsulation: ViewEncapsulation.None  // Use to disable CSS Encapsulation for this component
})

Anda dapat menemukan info selengkapnya tentang enkapsulasi tampilan di artikel ini .

Bunuh Diri Komersial
sumber
3
Menonaktifkan tampilan enkapsulasi menerapkan semua CSS di komponen Anda secara global.
Vedran
17
Jangan gunakan ViewEncapsulation.None! Ini akan membuat banyak kerusakan dengan membuat gaya tersebut mungkin bocor ke komponen lain.
Alex Klaus
1
@AlexKlaus, setuju, itu sebabnya saya sebutkan dalam jawaban, bahwa itu tidak ideal. Sebenarnya, saya menggunakannya hanya satu kali untuk menerapkan gaya berulang yang dapat dibagikan ke komponen Material Angular. Jika Anda mencoba menonaktifkan enkapsulasi, Anda mungkin akan mengalami kekacauan di beberapa titik. Ada baiknya mengetahui tentang opsi ini, tetapi jangan gunakan saat Anda tidak yakin benar-benar membutuhkannya.
Bunuh Diri Komersial
29

Saya akan menekankan pentingnya membatasi ::ng-deepke hanya anak-anak dari sebuah komponen dengan mengharuskan induk menjadi kelas css yang dienkapsulasi.

Agar ini berfungsi, penting untuk menggunakan ::ng-deepafter parent, bukan sebelumnya, jika tidak, ini akan berlaku untuk semua kelas dengan nama yang sama saat komponen dimuat.

Komponen css:

.my-component ::ng-deep .mat-checkbox-layout {
    background-color: aqua;
}

Template komponen:

<h1 class="my-component">
    <mat-checkbox ....></mat-checkbox>
</h1>

Menghasilkan (Angular dihasilkan) css:

.my-component[_ngcontent-c1] .mat-checkbox-layout {
    background-color: aqua;
}

EDIT:

Anda dapat mencapai perilaku yang sama dengan menggunakan :hostkata kunci alih-alih membuat kelas css baru.

:host ::ng-deep .mat-checkbox-layout
Vedran
sumber
5
Bung, jawaban Anda my-component ::ng-deep...baru saja menyelamatkan hari saya. Saya menghabiskan sepanjang hari mencoba menerapkan gaya untuk komponen saya dengan ng-deep dan menimpa semua komponen saya, dari seluruh aplikasi saya.
Cristiano Bombazar
2
Perlu diperhatikan: "Untuk mencakup gaya yang ditentukan ke komponen saat ini dan semua turunannya [tetapi tidak secara global], pastikan untuk menyertakan: host selector before :: ng-deep." Dari: angular.io/guide/component-styles
StvnBrkdll
1
@CristianoBombazar - Anda akan mendapatkan perilaku yang sama dengan :hostkata kunci - menambahkan catatan ke jawaban untuk kejelasan.
Vedran
23

Pastikan untuk tidak melewatkan penjelasan :host-contextyang langsung ::ng-deepdi atas di panduan sudut: https://angular.io/guide/component-styles . Penafian: Saya melewatkannya sampai sekarang dan berharap bisa melihatnya lebih cepat.

::ng-deepsering kali diperlukan jika Anda tidak menulis komponen dan tidak memiliki akses ke sumbernya, tetapi :host-contextbisa menjadi opsi yang sangat berguna saat Anda melakukannya.

Misalnya saya memiliki <h1>tajuk hitam di dalam komponen yang saya rancang, dan saya ingin kemampuan untuk mengubahnya menjadi putih saat ditampilkan pada latar belakang bertema gelap.

Jika saya tidak memiliki akses ke sumber, saya mungkin harus melakukan ini di css untuk orang tua:

.theme-dark widget-box ::ng-deep h1 { color: white; }

Tetapi sebaliknya dengan :host-contextAnda dapat melakukan ini di dalam komponen.

 h1 
 {
     color: black;       // default color

     :host-context(.theme-dark) &
     {
         color: white;   // color for dark-theme
     }

     // OR set an attribute 'outside' with [attr.theme]="'dark'"

     :host-context([theme='dark']) &
     {
         color: white;   // color for dark-theme
     }
 }

Ini akan mencari di mana saja dalam rantai komponen .theme-darkdan menerapkan css ke h1 jika ditemukan. Ini adalah alternatif yang baik untuk terlalu mengandalkan ::ng-deepyang sementara sering diperlukan agak anti-pola.

Dalam hal &ini diganti dengan h1(begitulah cara kerja sass / scss) sehingga Anda dapat menentukan css 'normal' dan bertema / alternatif tepat di samping satu sama lain yang sangat berguna.

Berhati-hatilah untuk mendapatkan angka yang benar :. Karena ::ng-deepada dua dan :host-contexthanya satu.

Simon_Weaver
sumber
Anda juga dapat menggunakan :host(.theme-dark)jika Anda tidak ingin mewarisi theme-darkdari komponen induk mana pun. Ini sepenuhnya tergantung pada desain css situs Anda. Atribut juga bisa sangat berguna dan dapat digabungkan dengan cara yang canggih di css saja:host([theme='dark']:not([dayofweek='tuesday'))
Simon_Weaver
Juga perhatikan bahwa ini mengikuti aturan css normal, jadi jika Anda memiliki komponen seperti yang dijelaskan di atas (dengan css konteks-host) di dalam wadah yang memiliki .theme-lightkelas ini pada gilirannya bersarang di dalam wadah dengan .theme-darkitu masih akan mengambil theme-darkdan menerapkan css. Tapi ini adalah solusi yang bagus untuk kelas tipe 'modernizr', atau jika Anda memiliki set tema secara global dan hanya sekali.
Simon_Weaver
Dapatkah saya menggunakan: host-context daripada :: ng-deep?
eddy
@eddy Saya terlalu mengantuk sekarang untuk sepenuhnya memikirkan hal ini, tetapi konteks host hampir seperti ng-deep tetapi naik ke pohon DOM alih-alih turun. Jadi ini sama sekali tidak setara tetapi Anda bisa
Simon_Weaver
2

Hanya pembaruan:

Anda harus menggunakan, ::ng-deepbukan /deep/yang sepertinya sudah usang.

Per dokumentasi:

Kombinator turunan shadow-piercing tidak digunakan lagi dan dukungan sedang dihapus dari browser dan alat utama. Karena itu kami berencana untuk melepaskan dukungan di Angular (untuk semua 3 dari / deep /, >>> dan :: ng-deep). Sampai saat itu :: ng-deep harus dipilih untuk kompatibilitas yang lebih luas dengan alat tersebut.

Anda bisa menemukannya di sini

Balázs Takács
sumber
5
Dalam teks ini dengan jelas mengatakan :: ng-deep juga tidak digunakan lagi: "kami berencana untuk melepaskan dukungan di Angular (untuk semua 3 dari / deep /, >>> dan :: ng-deep)".
adripanico
-2

Gunakan :: ng-deep dengan hati-hati. Saya menggunakannya di seluruh aplikasi saya untuk mengatur warna toolbar desain material ke warna yang berbeda di seluruh aplikasi saya hanya untuk menemukan bahwa ketika aplikasi sedang menguji warna toolbar menginjak satu sama lain. Ketahuilah itu karena gaya ini menjadi global, lihat artikel ini Berikut adalah solusi kode yang berfungsi yang tidak masuk ke komponen lain.

<mat-toolbar #subbar>
...
</mat-toolbar>

export class BypartSubBarComponent implements AfterViewInit {
  @ViewChild('subbar', { static: false }) subbar: MatToolbar;
  constructor(
    private renderer: Renderer2) { }
  ngAfterViewInit() {
    this.renderer.setStyle(
      this.subbar._elementRef.nativeElement, 'backgroundColor', 'red');
  }

}
Posting Impatica
sumber