:: ng-deep 대신 사용할 것


93

라우터 콘센트에 배치 된 요소를 각도로 스타일링하고 생성 된 요소의 너비가 100 %인지 확인하고 싶습니다.

대부분의 답변에서 ::ng-deep선택기를 사용해야한다는 것을 알지만 Angular의 문서 에서는 더 이상 사용되지 않습니다. 에 대한 대안이 ::ng-deep있습니까?


2
::ng-deep아무데도 가지 않습니다. 항상 활성화 할 수있는 설정입니다. 대규모 커뮤니티 반발 없이는 지금 제거 할 수있는 방법이 전혀 없습니다. 이 검색 돌아올 얼마나 많은 결과에서 봐 github.com/search?q=%3A%3Ang-deep&type=Code는 - 그것은 CSS의 말처럼 !important속성은 사라질 것입니다
Simon_Weaver

잘 모르겠습니다. 모노 리포지토리 (여러 개의 상당히 큰 엔터프라이즈 앱)에서 호기심으로 프로젝트 전체를 검색했으며 69 개의 ​​참조 만 나왔습니다. 나는 그것이 지원 중단에서 벗어나기 위해 허용되는 리팩터링이라고 생각하며 대안을 가져올 때마다 기꺼이 할 것입니다. 게다가 !importantCSS 사양에서 중요한 위치를 차지하는 반면 ::deep항상 제안에 불과했습니다.
dudewad

답변:


103

FWIW 내 연구에서 ng-deep 또는 기타 적용 가능한 대안에 대한 대체품을 찾지 못했습니다. 이것은 Angular 팀이 처음에 .NET Framework와 같은 선택기가 있었던 shadow dom의 W3C 사양을 연기하고 있기 때문 deep입니다. 그러나 W3c는 이후 권장 사항을 제거했지만 새 권장 사항으로 대체하지는 않았습니다. 그렇게 될 때까지 Angular 팀은 계속 ::ng-deep사용할 수 있고 대안을 사용할 수 있지만 W3C 초안의 보류 상태로 인해 더 이상 사용되지 않는 상태입니다. 지금은이를 백업 할 문서를 찾는 데 시간을 할애 할 수 없지만 최근에 확인했습니다.

간단히 말해서 : ::ng-deep교체가 생성 될 때까지 및 그 대안을 계속 사용하십시오. 사용 중단은 실제 변경 사항이 구체화 될 때마다 사람들이 눈을 멀게하지 않도록 초기 알림 일뿐입니다.

- 업데이트 -

https://drafts.csswg.org/css-scoping-1/ 관심이있는 경우 제안 초안이 있습니다. 그들은 Shadow dom 트리 내의 요소에 대한 강력한 선택기 세트를 작업하고있는 것으로 보입니다. 일단 승인되면이 사양이 앵귤러 클론이있는 경우이를 알릴 것이라고 생각합니다 (즉, 앵귤러가 브라우저에서 실행되면 자체 선택기를 구현할 필요가 없습니다).


이에 동의하지만 사용되지 않는 프레임 워크 (및 브라우저) 기능을 사용하여 의도적으로 새 코드를 작성하는 것은 권장하지 않습니다.
MT_

7
나도 그렇다. 그러나 여기에 분명하게 설명되어있는 대안은 없다. 도움이 될만한 제안이 있습니까?
dudewad

1
내가 빨리 생각할 수있는 유일한 대안은 구성 요소의 중첩을 리팩토링하는 것입니다. 시간보다 더 많은 작업이 필요하지만 다른 이점을 얻을 수 있습니다.
MT_

32
타사 라이브러리를 사용 ::ng-deep하면 (사이트가 어떻게 보이는지에 대해 관심이 있다면) 가끔씩 사용하는 것을 피하는 것이 사실상 불가능합니다. 심지어 각진 재료와 같은 경우에도 마찬가지입니다. 몇 달 동안 수정되지 않은 버그가 있으며 해결 방법에는 종종 ng-deep이 포함됩니다. 그리고 더 이상 사용되지 않는 '깊은'선택자를 혼동하지 마십시오. ::ng-deep확실히 가장 사용되지 않는 선택자 입니다.
Simon_Weaver

1
예 이것은 전체 시스템에서 가장 추악한 부분 중 하나입니다. 그러나 캡슐화는 캡슐화입니다. CSS에서 :: ng-deep을 명시 적으로 사용하여 경계를 허물거나 프로그래밍 방식으로 수행해야합니다. 때때로 컴포넌트 태그에 속성을 사용하여 컴포넌트가 어떤 "모드"에 있는지 (예 : 컨텍스트) 나타내면 스타일은 다음과 같은 속성 선택기를 통해 :: ng-deep없이 자식 컴포넌트에 존재할 수 있습니다. :host[some-context] {}-it 원하는 유연성 / 이동성에 따라 다릅니다. 나는 어느 쪽이든 좋아하지 않지만 이것이 캡슐화의 세계입니다.
dudewad

20

더 이상 사용되지 않는 ::ng-deep것을 우회하기 위해 일반적으로 비활성화 ViewEncapsulation합니다. 이것이 최선의 방법은 아니지만 저에게 도움이되었습니다.

을 비활성화하려면 ViewEncapsulation구성 요소에서 다음을 수행하십시오.

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

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

export class HeaderComponent {

}

이렇게하면이 구성 요소의 .scss 스타일이 전체 응용 프로그램에 전역으로 적용됩니다. 스타일이 상위 및 형제 구성 요소로 연결되는 것을 허용하지 않으려면 전체 scs를 다음과 같이 선택기로 래핑합니다.

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

이제 여기에 지정된 스타일은 하위 구성 요소로 내려가므로 CSS 선택기를 추가로 구체적으로 지정하고 CSS를 추가 할 때 p와 q를 염두에 두어야합니다 (Angular 앱에 지정된 하위 선택기를 추가 한 다음 해당 스타일을 추가 할 수 있음).

위의 단락 때문에 최선의 접근 방식은 아니라고 말하지만 이것은 저에게 도움이되었습니다.


12
이것은 해결 방법 일 뿐이며 대규모 프로젝트가있는 경우 스위치를 끄면 ViewEncapsulation이러한 스타일이 모든 구성 요소에 누출 될 수 있으므로 많은 피해가 발생합니다. 이 기능은 현명하고 충분히 이해하여 사용해야합니다
mpro

5
@mpro 이해합니다. 이것이 제가 경고를 한 이유이며 이것이 최선의 접근 방식이 아니라고 말하며 p와 q를 염두에두고 더욱 구체적이어야합니다. 저에게는이 접근 방식이 지금까지 잘 작동했습니다. :: ng-deep은 지원 중단으로 표시되며 이는 해결 방법입니다.
AliF50

1
솔직히 말하면 이것이 지원 중단 위협 때문에 그렇게했다면 도달하기에는 끔찍한 결론이라고 생각합니다. 네, 당신이 많이 알고 있다는 것을 압니다.하지만 저는 당신이 이것을함으로써 발을 쏘고 있다고 생각합니다. 뷰 캡슐화는 여러 가지 이유로 매우 유용합니다. 그러나 그것은 앵귤러 팀의 누군가가 논리적 해결 방법없이 그것을 비난하고 많은 사람들을 혼란으로 이끄는 것만 큼 나쁘지는 않습니다. 하루가 끝날 때에도 웹 브라우저를위한 코드를 작성하고 있습니다. 일종의 독점 각도 엔진이 아닙니다.
Simon_Weaver

2
@Simon_Weaver 귀하의 의견을 존중하고 공유해 주셔서 감사합니다. 사용 중단을 피하는 데 사용했던 것이기 때문에 나는 그것을 표면화하고 있습니다. 나는 또한 경고를 드러냈다.
AliF50

3
@ AliF50 "폐기물 순환"은 실제로 문제가 아닙니다. 여기서 진짜 문제는, 저는 제 인생에서 이것을 본 적이 없었습니다. 그들은 대안의 이름을 지정하지 않고 그것을 더 이상 사용 하지 않습니다 . 내 대답 (위에서 받아 들여진 것)은 사양과 일치하기 위해 (W3C가 더 이상 사용하지 않음) 이유에 대한 내 가설을 설명합니다. 그러나 제안서를 읽으면 :: ng-deep이 적절한 대안으로 대체되는 것처럼 보입니다. 즉, 사용할 수있게되면 문자 그대로 요구하는 접근 방식이 아닌 :: ng-deep 참조를 업데이트하기 만하면됩니다. 전체 애플리케이션을 재 설계합니다.
dudewad

14

딥 스타일에 대한 간단하고 쉬운 대안은 상위 구성 요소의 요소 선택기를 사용하는 일반적인 스타일입니다. 따라서 hero-details.component.css에 이것을 가지고 있다면 :

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

styles.css에서 다음과 같이됩니다.

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

기본적으로 딥 스타일은 캡슐화되지 않은 스타일이므로 개념적으로는 구성 요소 스타일보다 일반적인 스타일처럼 보입니다. 개인적으로 더 이상 딥 스타일을 사용하지 않을 것입니다. 주요 버전 업데이트의 주요 변경 사항은 정상이며 더 이상 사용되지 않는 기능 제거는 공정한 게임입니다.


1
와우, 이제 멍청 해. 감사! 다른 프런트 엔드 프레임 워크에서 오는 것은 불가능하다고 생각했습니다
Rafael Vidaurre

1
이것은 정말 유용합니다. :: ng-deep이 대체하지 않고 오랫동안 사용되지 않는다는 것은 아주 작은 일입니다 (: host :: ng-deep은 예상대로 작동하지만 사용되지 않는 것을 사용하고 싶지 않습니다).
Alexei

6

누군가가 전에 언급했듯이 타사 라이브러리를 사용하는 경우 가끔씩 사용하지 않는 것이 사실상 불가능합니다 ::ng-deep. 그러나 ::ng-deep브라우저에서 더 이상 지원되지 않는 이전 프로젝트에 대해 무엇을 할 예정 입니까?

그 순간을 준비하기 위해 다음을 제안합니다.

  1. ViewEncapsulation.None을 현명하게 사용하십시오 . 이는 더 깊은 구성 요소에 액세스해야하는 구성 요소에만 해당됩니다.
@Component({
      selector: 'app-example',
      templateUrl: './example.component.html',
      styleUrls: ['./example.component.scss'],
      encapsulation: ViewEncapsulation.None
    })
  1. 이제 충돌과 CSS 이상을 피하기 위해 (원칙적으로) 항상 컴포넌트의 템플릿을 클래스로 래핑해야합니다. 따라서 example.component.html은 다음과 같아야합니다.
<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. 다시 말하지만, 모든 단일 SCSS 파일의 첫 번째 줄은 구성 요소 컨테이너를 대상으로합니다. 캡슐화 가 없으므로 해당 클래스를 대상으로 타사 구성 요소를 수정할 수 있습니다. 즉, example.component.scss 는 다음과 같아야합니다.
.app-example-container {
/* All the CSS code goes here */
.mat-tab-group .mat-tab-label {color: red;}
}

2

이것은 :: ng-deep의 일반적인 대체물이 아니지만 질문 작성자가 설명한 사용 사례에 대한 것입니다.

라우터 콘센트에 의해 삽입 된 요소의 스타일을 지정하려는 특수한 경우 CSS의 인접 인접 선택기를 사용하는 우아한 솔루션이 있습니다.

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

이것은 라우터-아웃렛의 직접 이웃 인 모든 요소에 적용됩니다.

추가 정보 :
https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_combinator
https://angular.io/guide/router#router-outlet


1
이 선택기를 사용하지 않는 것이 좋습니다. 이것은 특히 애플리케이션이 커질 때 말 그대로 충돌의 악몽을 여는 것처럼 보입니다. 게다가 * 선택기는 말 그대로 CSS 존재에서 가장 느린 단일 선택기입니다.
dudewad

@dudewad * 선택자는 가장 느린 선택자이지만 전체 체인 / 트리가 아닌 문자 그대로 다음 형제 (+)에만 적용되므로 명목상의 차이 만 만들어야합니다.
Erik Philips

@ErikPhilips CSS 선택기는 오른쪽에서 왼쪽으로 구문 분석되므로 실제로는 최악의 시나리오입니다.
dudewad

@dudewad 우리가 뭔가를 놓치고 있다고 생각합니다. *최악의 시나리오에 의해 밀접하게 따라하지 않습니다 element *하지만 element + *어떤 경우 처음 두 근처입니다.
Erik Philips

모르겠어요 ... 테스트 한 적이 없습니다. 이것은 CSS 파서가 자신의 작업을 수행하는 방법에 대해 제가 알고있는 것을 기반으로합니다.
dudewad

1

기본 캡슐화를 변경하지 않기 위해 구성 요소에 대한 전역 스타일을 추가하는 도우미를 작성했습니다.

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

결과:

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.