Yerine ne kullanılmalı :: ng-deep


94

Yönlendirici çıkışı tarafından yerleştirilen bir öğeyi açısal olarak biçimlendirmeye çalışıyorum ve oluşturulan öğenin% 100 genişliğe sahip olduğundan emin olmak istiyorum

Yanıtların çoğundan, ::ng-deepseçiciyi kullanmam gerektiğini görüyorum , ancak Angular'ın belgelerine göre bu, kullanımdan kaldırılıyor. Bir alternatif var mı ::ng-deep?


2
::ng-deephiçbir yere gitmiyor. Her zaman etkinleştirebileceğiniz bir ayar olacaktır. Artık büyük bir topluluk tepkisi olmadan onu kaldırabilmelerinin hiçbir yolu yok. Bu arama için geri gelmek kaç sonuç bak github.com/search?q=%3A%3Ang-deep&type=Code - bu css demek gibi !importantözelliği ortadan kaybolacak
Simon_Weaver

Bilmiyorum - mono-repomuzda (çok sayıda oldukça büyük kurumsal uygulama) meraktan proje çapında bir araştırma yaptım ve sadece 69 referansla çıktım. Bunun kullanımdan kaldırılmanın kesinlikle kabul edilebilir bir refaktör olduğunu ve alternatifi ortaya çıkardıklarında bunu memnuniyetle yapacağını düşünüyorum. Ayrıca, !importantCSS spesifikasyonunda önemli bir yere sahipken ::deep, her zaman sadece bir teklifti.
dudewad

Yanıtlar:


103

FWIW Araştırmamda, ng-deep veya diğer uygulanabilir alternatiflerin yerini alacak herhangi bir şey bulamadım. Bunun nedeni, inanıyorum ki, Angular ekibi, başlangıçta gibi seçicilere sahip olan gölge dom üzerindeki W3C spesifikasyonunu erteliyor deep. Bununla birlikte, W3c o zamandan beri tavsiyeyi kaldırdı, ancak yenisiyle değiştirmedi. Bu olana kadar, Angular ekibinin devam edeceğini ::ng-deepve alternatiflerinin mevcut olacağını , ancak W3C taslaklarının bekleme durumu nedeniyle kullanımdan kaldırılmış durumda olacağını düşünüyorum. Şu anda bunu yedekleyecek belgeleri bulmaya zaman ayıramıyorum, ancak yakın zamanda gördüm.

Uzun lafın kısası: ::ng-deepBir yedek oluşturulana kadar ve alternatiflerini kullanmaya devam edin - kullanımdan kaldırma sadece erken bir bildirimdir, böylece gerçek değişiklik gerçekleştiğinde insanlar kör kalmaz.

- GÜNCELLEME -

https://drafts.csswg.org/css-scoping-1/ İlgilendiğiniz takdirde teklif taslağı burada. Görünüşe göre gölge dom ağacı içindeki öğeler için sağlam bir seçici seti üzerinde çalışıyorlar; Bu spesifikasyon, bir kez onaylandıktan sonra, eğer varsa açısal klonu bilgilendireceğini düşünüyorum (yani, açısal, tarayıcılarda yayınlandıktan sonra kendi seçicilerini uygulamaya ihtiyaç duymayabilir).


Buna katılıyorum, ancak kullanımdan kaldırılmış çerçeve (ve tarayıcı) işlevselliğini kullanarak kasıtlı olarak yeni kod yazmanızı önermem.
MT_

7
Ben de yapardım. Ama alternatif yok, bence burada hatasız bir şekilde ana hatları çiziliyor. Bu konuda yardımcı olacak herhangi bir öneriniz var mı?
dudewad

1
Hızlıca düşünebildiğim tek alternatif, bileşenlerin yerleştirilmesini yeniden düzenlemek olabilir, bu sizin için ayırdığınız zamandan daha fazla iş olabilir, ancak başka faydalar sağlayabilir ...
MT_

32
Üçüncü taraf bir kitaplıkla, ::ng-deepköşeli malzeme gibi bir şeyle bile arada bir kullanmak zorunda kalmaktan kaçınmak (sitenizin nasıl göründüğünü umursuyorsanız) neredeyse imkansızdır . Aylarca düzeltilmeyen hatalar var ve geçici çözümler genellikle ng derinliğini içerir. Ve farklı, kullanımdan kaldırılan 'derin' seçicileri karıştırmayın - ::ng-deepkesinlikle en az kullanımdan kaldırılan seçenektir.
Simon_Weaver

1
Evet, bu tüm sistemin en çirkin kısımlarından biri. Ancak kapsülleme, kapsüllemedir. Ya css'de :: ng-deep'u açıkça kullanarak sınırı aşmanız gerekir, ya da bunu programatik olarak yapmanız gerekir. Bazen bir bileşenin hangi "modda" (yani bağlamda) olduğunu belirtmek için bileşen etiketinde bir öznitelik kullanırız ve daha sonra stiller bir öznitelik seçici aracılığıyla aşağıdaki gibi alt bileşende (w / o :: ng-deep) yaşayabilir: :host[some-context] {}- it ne tür bir esneklik / taşınabilirlik istediğinize bağlıdır. Her iki yolu da sevmiyorum ama bu kapsülleme dünyası.
dudewad

20

Kullanımdan kaldırılanı atlamak için ::ng-deepgenellikle devre dışı bırakırım ViewEncapsulation. Bu en iyi yaklaşım olmasa da bana iyi hizmet etti.

Devre dışı bırakmak ViewEncapsulationiçin bileşeninizde aşağıdakileri yapın:

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

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

export class HeaderComponent {

}

Bu, bu bileşendeki .scss stillerini tüm uygulama için global hale getirecektir. Stillerin zincirde üst ve kardeş bileşenlere çıkmasına izin vermemek için, tüm scss'yi seçici ile şu şekilde sarın:

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

Şimdi, burada belirtilen stiller alt bileşenlere gidecektir, bu nedenle css seçicilerinizde ekstra spesifik olmanız ve CSS eklerken p'lerinize ve q'larınıza dikkat etmeniz gerekir (belki Angular uygulamanızda ve ardından stillerinde belirtilen alt seçiciyi ekleyin).

Yukarıdaki paragraf nedeniyle en iyi yaklaşım olmadığını söylüyorum, ama bu bana iyi hizmet etti.


12
Bu sadece geçici bir çözümdür ve büyük bir projeniz varsa, kapatmak ViewEncapsulation, bu stillerin tüm bileşenlere sızmasını mümkün kılarak çok fazla zarar verecektir. Bu özellik akıllıca ve tam anlayışla kullanılmalıdır
mpro

5
@mpro Anlıyorum, bu yüzden uyarıyı verdim ve bunun en iyi yaklaşım olmadığını söyledim ve p'lerinize ve q'larınıza dikkat etmeniz ve ekstra spesifik olmanız gerekiyor. Benim için bu yaklaşım şu ana kadar iyi çalıştı. :: ng-deep, kullanımdan kaldırılmak üzere işaretlenmiştir ve bu bir geçici çözümdür.
AliF50

1
Açıkçası, bunu reddetme tehdidi nedeniyle yaptıysanız, bunun ulaşılması gereken korkunç bir sonuç olduğunu düşünüyorum. Evet, senin de bunu anladığını biliyorum, ama gerçekten bunu yaparak kendini ayağından vurduğunu düşünüyorum. Görüntüleme kapsülleme birçok nedenden dolayı çok kullanışlıdır. Bununla birlikte, açısal ekipte herhangi bir mantıksal çözüm olmadan onu terk eden ve birçoklarının kafa karışıklığına yol açtığı kadar kötü değil. Günün sonunda hala bir web tarayıcısı için kod yazıyorsunuz - bir tür özel açısal motor değil.
Simon_Weaver

2
@Simon_Weaver Fikrinize saygı duyuyorum ve paylaştığınız için teşekkürler. Bunu yüzeye çıkarıyorum çünkü kullanımdan kaldırmayı atlatmak için kullandığım şey buydu. Ayrıca uyarıları da ortaya çıkardım.
AliF50

3
@ AliF50 "Kullanımdan kaldırmayı aşmak" gerçekten bir şey değil. Buradaki asıl sorun şu ki, bunu hayatımda daha önce hiç görmedim, bir alternatif isimlendirmeden onu reddettiler . Cevabım (yukarıda kabul edilen), spesifikasyona uymak için neden (W3C bunu reddetti) konusundaki hipotezimi açıklıyor. Bununla birlikte, önerileri okursanız, şöyle görünür :: ng-deep uygun bir alternatifle değiştirilecek, bu da mevcut olduğunda, kelimenin tam anlamıyla çağrıda bulunan yaklaşımınız yerine :: ng-derin referanslarınızı güncellemeniz anlamına gelir. tüm uygulamayı yeniden tasarlamak.
dudewad

15

Derin bir stile basit ve kolay bir alternatif, ana bileşenin öğe seçicisini kullanan yaygın bir stildir. Yani, bunu hero-details.component.css dosyasında bulundurduysanız:

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

Styles.css'de şu hale gelecekti:

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

Temelde derin bir stil, kapsüllenmemiş bir stildir, bu yüzden kavramsal olarak bana bir bileşen stilinden çok ortak bir stil gibi görünüyor. Şahsen ben artık derin stiller kullanmam. Büyük sürüm güncellemelerinde değişikliklerin kırılması normaldir ve kullanımdan kaldırılan özelliklerin kaldırılması adil bir oyundur.


1
Vay canına, şimdi kendimi aptal gibi hissediyorum. Teşekkürler! Diğer ön uç çerçevelerden
gelince

1
Bu gerçekten kullanışlıdır. Ne yazık ki :: ng-deep, bir değişiklik yapılmadan çok uzun süre kullanımdan kaldırıldı (: host :: ng-deep beklendiği gibi çalışıyor, ancak kullanımdan kaldırılmış şeyleri kullanmak istemiyorum).
Alexei

6

Daha önce de belirtildiği gibi, üçüncü taraf bir kitaplık kullanıyorsanız, arada bir kullanmak zorunda kalmamak neredeyse imkansızdır ::ng-deep. Ancak ::ng-deep, tarayıcılar artık desteklenmediğinde önceki projelerinizle ilgili ne yapacaksınız ?

O ana hazır olmak için şunları önereceğim:

  1. ViewEncapsulation'ı akıllıca kullanın . Bu, yalnızca daha derin bileşenlere erişmesi gereken bileşenler için geçerlidir.
@Component({
      selector: 'app-example',
      templateUrl: './example.component.html',
      styleUrls: ['./example.component.scss'],
      encapsulation: ViewEncapsulation.None
    })
  1. Şimdi, çarpışmalardan ve CSS tuhaflığından kaçınmak için (kural olarak) bileşen şablonunuzu her zaman bir sınıfla sarmalısınız. Dolayısıyla, example.component.html şöyle olmalıdır:
<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. Yine, kural olarak, her bir SCSS dosyasının ilk satırı bileşen kabını hedefleyecektir. Kapsülleme olmadığından , üçüncü taraf bileşenlerini sınıflarını hedefleyerek değiştirebilirsiniz. Bununla birlikte, example.component.scss şöyle olmalıdır:
.app-example-container {
/* All the CSS code goes here */
.mat-tab-group .mat-tab-label {color: red;}
}

2

Bu, :: ng-deep için genel bir ikame değildir, ancak soru yazarı tarafından açıklanan kullanım durumu için:

Bir yönlendirici prizi tarafından eklenen öğenin stilini belirlemek istediğiniz özel durumda, CSS'de bitişik komşu seçiciyi kullanan zarif bir çözüm vardır:

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

Bu, bir yönlendirici çıkışının doğrudan komşuları olan tüm unsurlar için geçerli olacaktır.

Daha fazla okuma:
https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_combinator
https://angular.io/guide/router#router-outlet


1
Bu seçiciyi kullanmanızı tavsiye etmem. Bu, özellikle uygulamanız büyüdüğünde gerçek bir çarpışma kabusu açıyor gibi görünüyor. Üstelik * seçici, CSS varlığındaki tam anlamıyla tek en yavaş seçicidir.
dudewad

@dudewad * seçici en yavaş seçiciyken, yalnızca bir sonraki kardeşe (+) uygulanır, zincire / ağaca değil, bu nedenle yalnızca nominal bir fark yaratmalıdır.
Erik Philips

@ErikPhilips CSS seçicileri sağdan sola ayrıştırılır, bu nedenle bu aslında en kötü durum senaryosudur.
dudewad

@dudewad Sanırım bir şey eksik. *en kötü durum senaryosunu yakından takip eder, element *ancak element + *ilk ikisinin yakınında değildir.
Erik Philips

Bilmiyorum ... Test etmedim, bu sadece CSS ayrıştırıcılarının işlerini nasıl yaptıkları hakkında bildiklerime dayanıyor.
dudewad

1

Varsayılan kapsüllemeyi değiştirmekten kaçınmak için, bileşene genel stilleri ekleyen bir yardımcı yazdım:

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;
       }
    `]);
  }
}

sonuç:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.