Làm thế nào và ở đâu để sử dụng :: ng-deep?


91

Tôi mới sử dụng Angular 4, vậy có ai có thể giải thích cách sử dụng ::ng-deepAngular 4 không?

Trên thực tế, tôi muốn ghi đè một số thuộc tính CSS của các thành phần con từ các thành phần mẹ. Hơn nữa nó có được hỗ trợ trên IE11 không?


Kể từ /deep/::ng-deepđều bị phản đối, tôi đề nghị bạn hãy alook này câu trả lời stackoverflow.com/a/49308475/2275011 và bình luận để biết thêm chi tiết và giải pháp.
Ferie

Câu trả lời:


93

Thông thường bộ /deep/ “shadow-piercing”tổ hợp có thể được sử dụng để buộc một kiểu xuống child components. Bộ chọn này có bí danh >>> và bây giờ có một bí danh khác được gọi là :: ng-deep.

kể từ khi /deep/ combinatorkhông được dùng nữa, nó được khuyến khích sử dụng::ng-deep

Ví dụ:

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

css

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

nó sẽ được áp dụng cho các thành phần con


Nó có hỗ trợ cho IE11 không?
Jeyabalan Thavamani

2
Angular thực hiện phân tích cú pháp của nó - vì vậy bạn không cần phải lo lắng về khả năng tương thích.
Simon_Weaver

nó chỉ dành cho các thành phần con? như tôi nhớ và như tôi thấy trong một nhận xét khác, nó cũng dành cho các phần tử dom bên ngoài thành phần.
yaya

Tôi có thể xác nhận rằng nó cũng có các thành phần cha mẹ ... Chỉ có trường hợp và đã khó chịu vì điều đó.
Shadoweb

1
Tuyệt vời, nó hoạt động hoàn hảo.
Alfredo Zamudio

71

SỬ DỤNG

::ng-deep, >>>/deep/vô hiệu hóa tầm nhìn đóng gói cho các quy tắc CSS cụ thể, nói cách khác, nó mang lại cho bạn truy cập vào phần tử DOM, mà không phải là trong mã HTML của thành phần của bạn. Ví dụ: nếu bạn đang sử dụng Angular Material (hoặc bất kỳ thư viện nào khác của bên thứ ba như thế này), một số phần tử được tạo nằm ngoài khu vực thành phần của bạn (chẳng hạn như hộp thoại ) và bạn không thể truy cập trực tiếp các phần tử đó hoặc sử dụng CSS thông thường đường. Nếu bạn muốn thay đổi kiểu của các phần tử đó, bạn có thể sử dụng một trong ba điều đó, ví dụ:

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

Hiện tại, nhóm Angular khuyên bạn chỉ nên thực hiện các thao tác "sâu" với tính năng đóng gói chế độ xem EMULATED .

DEPRECATION

Các thao tác "sâu" cũng thực sự không được dùng nữa , NHƯNG hiện tại nó vẫn hoạt động vì Angular có hỗ trợ xử lý trước (đừng vội từ chối ::ng-deepngay hôm nay, trước tiên hãy xem các phương pháp không dùng nữa ).

Dù sao đi nữa, trước khi làm theo cách này, tôi khuyên bạn nên xem xét cách vô hiệu hóa cách tiếp cận đóng gói chế độ xem (cách này không lý tưởng lắm, nó cho phép các kiểu của bạn bị rò rỉ vào các thành phần khác), nhưng trong một số trường hợp, đó là cách tốt hơn. Nếu bạn quyết định tắt tính năng đóng gói chế độ xem, bạn nên sử dụng các lớp cụ thể để tránh giao cắt các quy tắc CSS và cuối cùng, tránh lộn xộn trong các bảng định kiểu của bạn. Thật dễ dàng để tắt ngay trong .tstệp của thành phần :

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

Bạn có thể tìm thêm thông tin về đóng gói xem trong này bài viết.


3
Việc tắt tính năng đóng gói chế độ xem sẽ áp dụng tất cả CSS trong thành phần của bạn trên toàn cầu.
Vedran

17
Không sử dụng ViewEncapsulation.None! Nó sẽ gây ra nhiều thiệt hại bằng cách làm cho những phong cách đó có thể bị rò rỉ vào các thành phần khác.
Alex Klaus

1
@AlexKlaus, đồng ý, đó là lý do tại sao tôi đã đề cập trong câu trả lời, rằng nó không lý tưởng. Trên thực tế, tôi đã sử dụng nó chỉ một lần để áp dụng các kiểu lặp lại được chia sẻ cho các thành phần Angular Material. Nếu bạn cố gắng vô hiệu hóa tính năng đóng gói, bạn có thể sẽ gặp rắc rối tại một số điểm. Thật tốt khi biết về tùy chọn này, nhưng đừng sử dụng nó khi bạn không hoàn toàn chắc chắn rằng mình cần đến tùy chọn này.
Tự sát thương mại

29

Tôi sẽ nhấn mạnh tầm quan trọng của việc giới hạn ::ng-deepthành phần con duy nhất của một thành phần bằng cách yêu cầu cha mẹ phải là một lớp css được đóng gói.

Để điều này hoạt động, điều quan trọng là phải sử dụng ::ng-deepsau cha mẹ, không phải trước đó, nếu không nó sẽ áp dụng cho tất cả các lớp có cùng tên tại thời điểm thành phần được tải.

Css thành phần:

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

Mẫu thành phần:

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

Kết quả (tạo góc cạnh) css:

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

BIÊN TẬP:

Bạn có thể đạt được hành vi tương tự bằng cách sử dụng :hosttừ khóa thay vì tạo một lớp css mới.

:host ::ng-deep .mat-checkbox-layout

5
người đàn ông, câu trả lời của bạn my-component ::ng-deep...vừa cứu được ngày của tôi. Tôi đã dành cả ngày để cố gắng áp dụng một phong cách cho thành phần của mình với ng-deep và đang ghi đè lên tất cả các thành phần của tôi, từ toàn bộ ứng dụng của tôi.
Cristiano Bombazar

2
Cần lưu ý: "Để phạm vi kiểu được chỉ định cho thành phần hiện tại và tất cả các thành phần con của nó [nhưng không phải trên toàn cục], hãy đảm bảo bao gồm: bộ chọn máy chủ trước :: ng-deep." Từ: angle.io/guide/component-styles
StvnBrkdll

1
@CristianoBombazar - bạn sẽ nhận được hành vi tương tự với :hosttừ khóa - đã thêm ghi chú vào câu trả lời để rõ ràng hơn.
Vedran

23

Hãy chắc chắn rằng bạn không bỏ lỡ phần giải thích :host-contextở trên ::ng-deeptrong hướng dẫn góc: https://angular.io/guide/component-styles . Tuyên bố từ chối trách nhiệm: Tôi đã bỏ lỡ nó cho đến bây giờ và ước tôi sẽ thấy nó sớm hơn.

::ng-deepthường cần thiết khi bạn không viết thành phần và không có quyền truy cập vào nguồn của nó, nhưng :host-contextcó thể là một tùy chọn rất hữu ích khi bạn làm vậy.

Ví dụ: tôi có một <h1>tiêu đề màu đen bên trong một thành phần tôi đã thiết kế và tôi muốn có khả năng thay đổi nó thành màu trắng khi nó được hiển thị trên nền theo chủ đề tối.

Nếu tôi không có quyền truy cập vào nguồn, tôi có thể phải thực hiện việc này trong css cho phụ huynh:

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

Nhưng thay vào đó, :host-contextbạn có thể làm điều này bên trong thành phần.

 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
     }
 }

Điều này sẽ tìm ở bất kỳ đâu trong chuỗi thành phần .theme-darkvà áp dụng css cho h1 nếu được tìm thấy. Đây là một giải pháp thay thế tốt cho việc dựa vào quá nhiều ::ng-deeptrong khi thường xuyên cần thiết lại có phần chống đối.

Trong trường hợp này, css &được thay thế bằng h1(đó là cách hoạt động của sass / scss) để bạn có thể xác định css 'bình thường' và theo chủ đề / thay thế của mình ngay cạnh nhau, rất tiện dụng.

Hãy cẩn thận để có được số lượng chính xác :. Vì ::ng-deepcó hai và :host-contextchỉ một.


Bạn cũng có thể sử dụng :host(.theme-dark)nếu bạn không muốn kế thừa theme-darktừ bất kỳ thành phần mẹ nào. Điều này sẽ hoàn toàn phụ thuộc vào thiết kế css trang web của bạn. Cũng thuộc tính có thể rất hữu ích và có thể được kết hợp theo những cách tinh vi trong css một mình:host([theme='dark']:not([dayofweek='tuesday'))
Simon_Weaver

Cũng lưu ý rằng điều này tuân theo các quy tắc css thông thường, vì vậy nếu bạn có một thành phần như được mô tả ở trên (với css ngữ cảnh máy chủ) bên trong một vùng chứa có một .theme-lightlớp, đến lượt nó được lồng bên trong một vùng chứa với .theme-darknó sẽ vẫn nhận theme-darkvà áp dụng css. Nhưng đây là một giải pháp tuyệt vời cho các lớp kiểu 'modernizr' hoặc nếu bạn có một chủ đề được đặt trên toàn cầu và chỉ một lần.
Simon_Weaver

Tôi có thể sử dụng: host-context thay vì :: ng-deep không?
xoáy

@eddy Bây giờ tôi quá buồn ngủ để suy nghĩ thấu đáo điều này, nhưng ngữ cảnh máy chủ gần giống như ng-deep nhưng sẽ LÊN cây DOM thay vì xuống. Vì vậy, nó hoàn toàn không tương đương nhưng bạn có thể
Simon_Weaver

2

Chỉ là một bản cập nhật:

Bạn nên sử dụng ::ng-deepthay vì /deep/có vẻ như không được dùng nữa.

Theo tài liệu:

Bộ tổ hợp con cháu xuyên qua bóng tối không được dùng nữa và hỗ trợ sẽ bị xóa khỏi các trình duyệt và công cụ chính. Do đó, chúng tôi có kế hoạch giảm hỗ trợ trong Angular (cho cả 3 / deep /, >>> và :: ng-deep). Cho đến lúc đó :: ng-deep nên được ưu tiên hơn để có khả năng tương thích rộng hơn với các công cụ.

Bạn có thể tìm thấy nó ở đây


5
Trong văn bản này, rõ ràng là :: ng-deep cũng không được chấp nhận: "chúng tôi dự định bỏ hỗ trợ trong Angular (cho cả 3 / deep /, >>> và :: ng-deep)".
adripanico

-2

Sử dụng :: ng-deep một cách thận trọng. Tôi đã sử dụng nó trong toàn bộ ứng dụng của mình để đặt màu thanh công cụ material design thành các màu khác nhau trong toàn bộ ứng dụng của mình chỉ để nhận thấy rằng khi ứng dụng đang thử nghiệm các màu thanh công cụ xen kẽ nhau. Hãy đến để tìm hiểu đó là vì những phong cách này trở nên toàn cầu, hãy xem bài viết này Đây là một giải pháp mã làm việc mà không bị tràn vào các thành phần khác.

<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');
  }

}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.