Apa yang harus digunakan sebagai pengganti :: ng-deep


94

Saya mencoba menata elemen yang ditempatkan oleh outlet router dalam sudut dan ingin memastikan bahwa elemen yang dihasilkan mendapat lebar 100%

Dari sebagian besar balasan, saya melihat bahwa saya harus menggunakan ::ng-deeppemilih, tetapi dari dokumen Angular sudah tidak digunakan lagi. Apakah ada alternatif lain ::ng-deep?


2
::ng-deeptidak akan kemana-mana. Ini akan selalu menjadi pengaturan yang dapat Anda aktifkan. Sama sekali tidak mungkin mereka dapat menghapusnya sekarang tanpa reaksi komunitas besar-besaran. Lihat berapa banyak hasil yang kembali untuk penelusuran ini github.com/search?q=%3A%3Ang-deep&type=Code - ini seperti mengatakan !importantproperti css akan menghilang
Simon_Weaver

Saya tidak tahu - Saya melakukan pencarian di seluruh proyek karena penasaran di mono-repo kami (beberapa aplikasi perusahaan yang cukup besar) dan hanya keluar dengan 69 referensi. Saya merasa itu jelas merupakan refactor yang dapat diterima untuk keluar dari deprecation dan dengan senang hati akan melakukannya setiap kali mereka memberikan alternatif. Selain itu, !importantmemiliki tempat penting dalam spesifikasi CSS padahal ::deepselalu hanya proposal.
dudewad

Jawaban:


103

FWIW Dalam penelitian saya, saya belum menemukan pengganti ng-deep atau alternatif lain yang berlaku. Ini karena, saya yakin, tim Angular menunda spesifikasi W3C pada shadow dom, yang awalnya memiliki penyeleksi seperti deep. Namun, W3c telah menghapus rekomendasi tersebut, tetapi tidak menggantinya dengan yang baru. Sampai itu terjadi, saya membayangkan bahwa tim Angular akan tetap ::ng-deepdan alternatifnya tersedia, tetapi dalam keadaan usang karena rancangan W3C yang tertunda. Saya tidak dapat meluangkan waktu untuk menemukan dokumentasi untuk mendukung ini sekarang tetapi saya melihatnya baru-baru ini.

Singkat cerita: Tetap gunakan ::ng-deepdan alternatifnya sampai penggantinya dibuat - penghentian hanya pemberitahuan awal sehingga orang tidak dibutakan setiap kali perubahan aktual terwujud.

- PEMBARUAN -

https://drafts.csswg.org/css-scoping-1/ Berikut adalah draf proposal jika Anda tertarik. Tampaknya mereka sedang mengerjakan satu set penyeleksi yang kuat untuk elemen dalam pohon dom bayangan; itu adalah spesifikasi ini, setelah disetujui, yang menurut saya akan menginformasikan klon sudut, jika bahkan ada satu (yaitu sudut mungkin tidak perlu menerapkan penyeleksi mereka sendiri setelah ini ditayangkan di browser).


Saya setuju dengan ini, tetapi saya tidak akan merekomendasikan menulis kode baru dengan sengaja menggunakan fungsionalitas kerangka kerja (dan browser) yang sudah usang.
MT_

7
Aku juga. Tapi tidak ada alternatif, yang menurutku tidak dijelaskan dengan jelas di sini. Apakah Anda punya saran untuk membantu?
dudewad

1
Satu-satunya alternatif yang dapat saya pikirkan dengan cepat adalah refactoring komponen bersarang, yang mungkin lebih banyak pekerjaan daripada waktu yang Anda miliki tetapi dapat menghasilkan manfaat lain ...
MT_

32
Dengan perpustakaan pihak ketiga, hampir tidak mungkin untuk menghindari penggunaan ::ng-deepsesekali (jika Anda benar-benar peduli dengan tampilan situs Anda) - bahkan dengan sesuatu seperti materi bersudut. Mereka memiliki bug yang tidak diperbaiki selama berbulan-bulan, dan penyelesaiannya sering kali melibatkan ng-deep. Dan jangan bingung dengan penyeleksi 'dalam' ::ng-deepyang tidak digunakan lagi - pasti yang paling tidak digunakan lagi.
Simon_Weaver

1
Ya, ini adalah salah satu bagian paling jelek dari keseluruhan sistem. Tapi enkapsulasi adalah enkapsulasi. Anda harus mendobrak batasan baik dengan secara eksplisit menggunakan :: ng-deep di css, atau Anda perlu melakukannya secara terprogram. Terkadang kita menggunakan atribut pada tag komponen untuk menunjukkan "mode" apa yang ada dalam komponen (yaitu konteks), dan kemudian gaya dapat hidup dalam komponen anak w / o :: ng-deep melalui pemilih atribut seperti: :host[some-context] {}- it tergantung pada jenis fleksibilitas / portabilitas yang Anda inginkan. Saya juga tidak terlalu suka tapi ini adalah dunia enkapsulasi.
dudewad

20

Untuk melewati yang tidak digunakan lagi ::ng-deep, saya biasanya menonaktifkan ViewEncapsulation. Meskipun ini bukan pendekatan terbaik, ini telah membantu saya dengan baik.

Untuk menonaktifkan ViewEncapsulation, lakukan hal berikut di komponen Anda:

import { Component, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.scss'],
  encapsulation: ViewEncapsulation.None
})

export class HeaderComponent {

}

Ini akan membuat gaya .scss dalam komponen ini global ke seluruh aplikasi. Agar gaya tidak naik rantai ke komponen induk dan saudara, bungkus seluruh scss dengan selektor seperti ini:

app-header {
  // your styles here and any child component styles can go here
}

Sekarang, gaya yang ditentukan di sini akan turun ke komponen anak-anak sehingga Anda harus ekstra spesifik dengan pemilih css dan memperhatikan p dan q Anda saat menambahkan CSS (mungkin tambahkan pemilih anak yang ditentukan dalam aplikasi Angular Anda dan kemudian gayanya).

Saya mengatakan ini bukan pendekatan terbaik karena paragraf di atas, tetapi ini telah membantu saya dengan baik.


12
Ini hanya solusi dan jika Anda memiliki proyek besar, mematikannya ViewEncapsulationakan membuat banyak kerusakan dengan membuat gaya tersebut mungkin bocor ke semua komponen. Fitur ini harus digunakan dengan bijak dan dengan pemahaman penuh
mpro

5
@mpro Saya mengerti, itulah mengapa saya memberikan peringatan dan mengatakan ini bukan pendekatan terbaik dan Anda harus memikirkan p dan q Anda dan harus ekstra spesifik. Bagi saya, pendekatan ini telah berhasil sejauh ini. :: ng-deep ditandai untuk tidak digunakan lagi dan ini adalah solusinya.
AliF50

1
Sejujurnya saya pikir ini adalah kesimpulan yang mengerikan untuk dicapai jika Anda melakukan ini karena ancaman penghinaan. Ya, saya tahu Anda mengakuinya, tetapi saya benar-benar berpikir Anda menembak diri sendiri dengan melakukan ini. Tampilan enkapsulasi sangat berguna karena berbagai alasan. Namun itu tidak seburuk siapa pun di tim sudut yang menolaknya tanpa solusi logis dan menyebabkan banyak kebingungan. Pada akhirnya, Anda masih menulis kode untuk browser web - bukan semacam mesin sudut berpemilik.
Simon_Weaver

2
@Simon_Weaver Saya menghormati pendapat Anda dan terima kasih telah berbagi. Saya hanya mengutarakannya karena itulah yang biasa saya hindari. Saya juga mengemukakan keberatannya.
AliF50

3
@ AliF50 "Mengakali depreksi" sebenarnya bukan apa-apa. Masalah sebenarnya di sini adalah, dan saya belum pernah melihat ini sebelumnya dalam hidup saya, mereka menolaknya tanpa menyebutkan alternatif . Jawaban saya (yang diterima di atas) menjelaskan hipotesis saya tentang mengapa mereka melakukan (W3C menghentikannya) agar selaras dengan spesifikasi. Namun, jika Anda membaca proposalnya, sepertinya :: ng-deep akan diganti dengan alternatif yang sesuai yang berarti ketika tersedia, Anda cukup memperbarui referensi :: ng-deep Anda, bukan pendekatan Anda yang membutuhkan merancang ulang seluruh aplikasi.
dudewad

15

Alternatif sederhana dan mudah untuk gaya dalam adalah gaya yang umum menggunakan pemilih elemen dari komponen induk. Jadi jika Anda memiliki ini di hero-details.component.css:

:host ::ng-deep h3 {
  font-style: italic;
}

Ini akan menjadi seperti ini di styles.css:

app-hero-details h3 {
  font-style: italic;
}

Pada dasarnya gaya dalam adalah gaya yang tidak dikemas sehingga secara konseptual tampak lebih seperti gaya yang umum bagi saya daripada gaya komponen. Secara pribadi saya tidak akan menggunakan gaya dalam lagi. Perubahan yang merusak adalah hal yang normal dalam pembaruan versi utama dan penghapusan fitur yang tidak berlaku lagi adalah hal yang wajar.


1
Wow, saya merasa bodoh sekarang. Terima kasih! Berasal dari kerangka kerja front-end lain, saya pikir ini tidak mungkin
Rafael Vidaurre

1
Ini sangat berguna. Sangat disayangkan bahwa :: ng-deep sudah tidak digunakan lagi begitu lama tanpa penggantinya (: host :: ng-deep berfungsi seperti yang diharapkan, tetapi saya tidak ingin menggunakan hal-hal yang sudah usang).
Alexei

6

Seperti yang dikatakan seseorang sebelumnya, jika Anda menggunakan pustaka pihak ketiga, hampir tidak mungkin untuk menghindari penggunaan ::ng-deepsesekali. Tapi apa yang akan Anda lakukan tentang proyek Anda sebelumnya ketika ::ng-deeptidak lagi didukung oleh browser?

Untuk bersiap menghadapi momen itu saya akan menyarankan yang berikut:

  1. Gunakan ViewEncapsulation.None dengan bijak. Yang diterjemahkan menjadi hanya untuk komponen-komponen yang perlu mengakses komponen yang lebih dalam.
@Component({
      selector: 'app-example',
      templateUrl: './example.component.html',
      styleUrls: ['./example.component.scss'],
      encapsulation: ViewEncapsulation.None
    })
  1. Sekarang, untuk menghindari benturan dan keanehan CSS Anda harus (sebagai aturan) selalu membungkus template komponen Anda dengan sebuah kelas. Jadi, example.component.html harus seperti:
<section class="app-example-container">
<!-- a third party component -->
<mat-tab-group>
<mat-tab label="First"></mat-tab>
<mat-tab label="Second"></mat-tab>
</mat-tab-group>
</section>
  1. Sekali lagi, menurut aturan, baris pertama dari setiap file SCSS akan menargetkan penampung komponen. Karena tidak ada Enkapsulasi, Anda dapat mengubah komponen pihak ketiga dengan menargetkan kelas mereka. Karena itu, example.component.scss harus seperti:
.app-example-container {
/* All the CSS code goes here */
.mat-tab-group .mat-tab-label {color: red;}
}

2

Ini bukan pengganti umum untuk :: ng-deep, tetapi untuk kasus penggunaan yang dijelaskan oleh penulis pertanyaan:

Dalam kasus khusus di mana Anda ingin memberi gaya pada elemen yang dimasukkan oleh outlet-router, ada solusi elegan dengan menggunakan selektor tetangga yang berdekatan di CSS:

router-outlet+* {
  /* styling here... */
}

Ini akan berlaku untuk semua elemen yang merupakan tetangga langsung dari outlet router.

Bacaan lebih lanjut:
https://developer.mozilla.org/en-US/docs/Web/CSS/Ad
Berdekatan_sibling_combinator https://angular.io/guide/router#router-outlet


1
Saya tidak akan merekomendasikan menggunakan pemilih ini. Ini sepertinya Anda membuka mimpi buruk tabrakan literal terutama saat aplikasi Anda berkembang. Selain itu, * selector secara harfiah adalah satu-satunya pemilih paling lambat dalam keberadaan CSS.
dudewad

@dudewad sementara * pemilih adalah pemilih paling lambat, ini hanya diterapkan ke saudara berikutnya (+), bukan seluruh rantai / pohon, jadi seharusnya hanya membuat perbedaan nominal.
Erik Philips

@ErikPhilips CSS selector diurai dari kanan ke kiri, jadi ini sebenarnya skenario terburuk.
dudewad

@udhad Saya pikir kita melewatkan sesuatu. *adalah skenario terburuk yang diikuti oleh element *tetapi element + *tidak ada yang mendekati dua yang pertama.
Erik Philips

Saya tidak tahu ... Saya belum mengujinya, ini hanya berdasarkan apa yang saya ketahui tentang bagaimana pengurai CSS melakukan tugasnya.
dudewad

1

Untuk menghindari mengubah enkapsulasi default, saya menulis pembantu yang menambahkan gaya global untuk komponen:

deepStyle.ts

import { ViewContainerRef } from '@angular/core';

export function deepStyle(vcr: ViewContainerRef, csss: string[]){
    let id = 'deep-' + vcr.element.nativeElement.tagName;
    let styleElement = document.getElementById('pierce-' + vcr.element.nativeElement.name);
    if(!styleElement){
        styleElement = document.createElement('style');
        styleElement.id = id;
        styleElement.innerHTML = csss.map(css => vcr.element.nativeElement.tagName + ' ' + css).join('\n');
        document.head.append(styleElement);
    }
}

my-component.ts

import { Component, ViewContainerRef } from '@angular/core';
import { deepStyle } from '../deepStyle';

@Component({
  selector: 'my-component',
  templateUrl: './my-component.html',
  styleUrls: ['./my-component.css']
})
export class MyComponent {
   constructor(vcr: ViewContainerRef) {
    deepStyle(vcr, [`
       img {
         height: 180px;
       }
    `]);
  }
}

hasil:

<head>
...
<style id="deep-MY-COMPONENT">
    MY-COMPONENT img {
      height: 180px;
    }
</style>
...
</head>

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.