Dùng gì thay cho :: ng-deep


94

Tôi đang cố tạo kiểu cho một phần tử được đặt bởi đầu ra bộ định tuyến theo góc cạnh và muốn đảm bảo rằng phần tử được tạo có chiều rộng là 100%

Từ hầu hết các câu trả lời, tôi thấy rằng tôi nên sử dụng ::ng-deepbộ chọn, nhưng từ tài liệu của Angular, nó không được dùng nữa. Có một thay thế cho ::ng-deep?


2
::ng-deepkhông đi đâu cả. Nó sẽ luôn là một cài đặt bạn có thể bật. Hoàn toàn không có cách nào họ có thể xóa nó ngay bây giờ mà không có phản ứng dữ dội từ cộng đồng. Xem có bao nhiêu kết quả trả lại cho tìm kiếm này github.com/search?q=%3A%3Ang-deep&type=Code - giống như nói rằng thuộc tính css !importantsẽ biến mất
Simon_Weaver

Tôi không biết - tôi đã thực hiện một cuộc tìm kiếm toàn dự án vì tò mò trong mono-repo của chúng tôi (nhiều ứng dụng dành cho doanh nghiệp khá lớn) và chỉ đưa ra được 69 tài liệu tham khảo. Tôi cảm thấy đó chắc chắn là một công cụ tái cấu trúc có thể chấp nhận được để chuyển sang trạng thái không dùng nữa và sẽ sẵn lòng làm điều đó bất cứ khi nào họ đưa ra giải pháp thay thế. Bên cạnh đó, !importantcó một vị trí quan trọng trong đặc tả CSS trong khi ::deepluôn chỉ là một đề xuất.
dudewad

Câu trả lời:


103

FWIW Trong nghiên cứu của mình, tôi không tìm thấy bất kỳ sự thay thế nào cho ng-deep hoặc các lựa chọn thay thế áp dụng khác. Điều này là do, tôi tin rằng, nhóm Angular đang trì hoãn thông số W3C trên bóng dom, ban đầu có các bộ chọn như deep. Tuy nhiên, W3c kể từ đó đã loại bỏ khuyến nghị, nhưng không thay thế nó bằng một khuyến nghị mới. Cho đến khi điều đó xảy ra, tôi tưởng tượng rằng nhóm Angular sẽ giữ lại ::ng-deepvà có sẵn các giải pháp thay thế, nhưng ở trạng thái không được dùng nữa do các bản nháp của W3C đang chờ xử lý. Tôi không thể dành thời gian để tìm tài liệu để sao lưu điều này ngay bây giờ nhưng tôi đã thấy nó gần đây.

Tóm lại: Hãy tiếp tục sử dụng ::ng-deepvà các lựa chọn thay thế cho đến khi tạo ra một sản phẩm thay thế - việc ngừng sử dụng chỉ là thông báo sớm để mọi người không bị che mắt bất cứ khi nào thay đổi thực sự xảy ra.

- CẬP NHẬT -

https://drafts.csswg.org/css-scoping-1/ Đây là bản nháp đề xuất nếu bạn quan tâm. Có vẻ như họ đang làm việc trên một tập hợp các bộ chọn mạnh mẽ cho các phần tử trong cây dom bóng; đó là thông số kỹ thuật này, một khi được chấp thuận, mà tôi nghĩ sẽ thông báo cho bản sao góc cạnh, nếu thậm chí có một bản sao (tức là góc cạnh có thể không cần triển khai các bộ chọn của riêng chúng khi nó hoạt động trong trình duyệt).


Tôi đồng ý với điều này, nhưng tôi không khuyên bạn nên viết mã mới có mục đích sử dụng chức năng khung (và trình duyệt) không dùng nữa.
MT_

7
Tôi cũng vậy. Nhưng không có giải pháp thay thế nào, mà tôi nghĩ rằng nó đã được phác thảo rõ ràng ở đây. Bạn có bất kỳ đề xuất để giúp với điều đó?
dudewad

1
Tôi chỉ thay thế có thể nhanh chóng nghĩ ra sẽ được sắp xếp làm tổ của các thành phần, có thể làm việc nhiều hơn bạn có thời gian cho nhưng có thể mang lại lợi ích khác ...
MT_

32
Với thư viện của bên thứ ba, hầu như không thể tránh khỏi việc thỉnh thoảng phải sử dụng ::ng-deepmột lần (nếu bạn quan tâm đến trang web của mình trông như thế nào) - ngay cả với những thứ như tài liệu góc cạnh. Chúng có những lỗi không được sửa trong nhiều tháng và cách giải quyết thường liên quan đến ng-deep. Và đừng nhầm lẫn giữa các bộ chọn 'sâu' không được dùng nữa - ::ng-deepchắc chắn là bộ chọn ít bị phản đối nhất.
Simon_Weaver

1
Vâng, đây là một trong những phần xấu xí nhất của toàn bộ hệ thống. Nhưng đóng gói là đóng gói là gì. Bạn phải phá bỏ ranh giới bằng cách sử dụng rõ ràng :: ng-deep trong css, hoặc bạn cần phải làm điều đó theo chương trình. Đôi khi chúng tôi sử dụng một thuộc tính trên thẻ thành phần để cho biết một thành phần đang ở "chế độ" nào (tức là ngữ cảnh) và sau đó các kiểu có thể tồn tại trong thành phần con w / o :: ng-deep thông qua một bộ chọn thuộc tính như: :host[some-context] {}- it phụ thuộc vào loại tính linh hoạt / tính di động mà bạn muốn. Tôi không thích cách nào cả nhưng đây là thế giới của sự đóng gói.
dudewad

20

Để bỏ qua lỗi không được dùng nữa ::ng-deep, tôi thường tắt ViewEncapsulation. Mặc dù đây không phải là cách tiếp cận tốt nhất, nhưng nó đã phục vụ tôi rất tốt.

Để tắt ViewEncapsulation, hãy làm như sau trong thành phần của bạ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 {

}

Điều này sẽ làm cho các kiểu .scss trong thành phần này chung cho toàn bộ ứng dụng. Để không cho phép các kiểu đi lên chuỗi tới các thành phần chính và anh chị em, hãy bao bọc toàn bộ phạm vi bằng bộ chọn như sau:

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

Bây giờ, các kiểu được chỉ định ở đây sẽ đi xuống các thành phần con, vì vậy bạn phải đặc biệt hơn với các bộ chọn css của mình và lưu ý đến chữ p và q của bạn khi thêm CSS (có thể thêm bộ chọn con được chỉ định trong ứng dụng Angular của bạn và sau đó là các kiểu của nó).

Tôi nói đó không phải là cách tiếp cận tốt nhất vì đoạn trên, nhưng điều này đã phục vụ tôi rất tốt.


12
Đây chỉ là cách giải quyết và nếu bạn có một dự án lớn, việc tắt ViewEncapsulationnó sẽ gây ra nhiều thiệt hại do làm cho những phong cách đó có thể bị rò rỉ vào tất cả các thành phần. Tính năng này nên được sử dụng một cách khôn ngoan và đầy đủ hiểu biết
mpro

5
@mpro Tôi hiểu, đó là lý do tại sao tôi đưa ra cảnh báo trước và nói rằng đây không phải là cách tiếp cận tốt nhất và bạn phải lưu ý đến chữ p và q của mình và phải thêm cụ thể. Đối với tôi, cách tiếp cận này đã hoạt động tốt cho đến nay. :: ng-deep được đánh dấu là không dùng nữa và đây là cách giải quyết.
AliF50

1
Thành thật mà nói, tôi nghĩ rằng đây là một kết luận khủng khiếp nếu bạn đã làm điều này vì sự phản đối bị đe dọa. Vâng, tôi biết bạn thừa nhận rất nhiều, nhưng tôi thực sự nghĩ rằng bạn đang tự bắn vào chân mình khi làm điều này. Chế độ xem đóng gói rất hữu ích vì nhiều lý do. Tuy nhiên, nó gần như không tệ bằng việc bất cứ ai trong nhóm góc cạnh phản đối nó mà không có bất kỳ giải pháp hợp lý nào và dẫn đến nhiều người nhầm lẫn. Vào cuối ngày, bạn vẫn đang viết mã cho một trình duyệt web - không phải một loại công cụ góc cạnh độc quyền nào đó.
Simon_Weaver

2
@Simon_Weaver Tôi tôn trọng ý kiến ​​của bạn và cảm ơn bạn đã chia sẻ. Tôi chỉ đang trình bày nó bởi vì nó là những gì tôi đã sử dụng để tránh khỏi sự phản đối. Tôi cũng nổi lên những cảnh báo.
AliF50

3
@ AliF50 "Phá vỡ deprectaion" không thực sự là một điều. Vấn đề thực sự ở đây là, và tôi chưa bao giờ thấy điều này trước đây trong đời, họ không dùng nó mà không đặt tên cho một giải pháp thay thế . Câu trả lời của tôi (câu trả lời được chấp nhận ở trên) giải thích giả thuyết của tôi về lý do tại sao họ đã làm (W3C không dùng nó) để phù hợp với thông số kỹ thuật. Tuy nhiên, nếu bạn đọc các đề xuất, có vẻ như :: ng-deep sẽ được thay thế bằng một giải pháp thay thế phù hợp, có nghĩa là khi nó có sẵn, bạn chỉ cần cập nhật các tham chiếu :: ng-deep của mình, thay vì cách tiếp cận của bạn gọi theo nghĩa đen tái cấu trúc toàn bộ ứng dụng.
dudewad

15

Cách thay thế đơn giản và dễ dàng cho kiểu sâu là kiểu phổ biến sử dụng bộ chọn phần tử của thành phần mẹ. Vì vậy, nếu bạn có điều này trong hero-details.component.css:

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

Nó sẽ trở thành điều này trong styles.css:

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

Về cơ bản, một phong cách sâu sắc là một phong cách không được đóng gói nên về mặt khái niệm, nó có vẻ giống một phong cách chung hơn là một phong cách thành phần. Cá nhân tôi sẽ không sử dụng phong cách sâu sắc nữa. Các thay đổi đột phá là bình thường trong các bản cập nhật phiên bản lớn và việc loại bỏ tính năng không dùng nữa là một trò chơi công bằng.


1
Wow, tôi cảm thấy chết lặng. Cảm ơn! Đến từ các khuôn khổ front-end khác, tôi nghĩ điều này là không thể
Rafael Vidaurre

1
Điều này thực sự hữu ích. Thật đáng tiếc khi :: ng-deep đã bị phản đối quá lâu mà không có người thay thế (: host :: ng-deep hoạt động như mong đợi, nhưng tôi không muốn sử dụng những thứ không dùng nữa).
Alexei

6

Như ai đó đã nói trước đây, nếu bạn đang sử dụng thư viện của bên thứ ba thì hầu như không thể tránh khỏi việc thỉnh thoảng phải sử dụng ::ng-deepmột lần. Nhưng bạn sẽ làm gì với các dự án trước đây của mình khi dự án ::ng-deepkhông còn được hỗ trợ bởi các trình duyệt?

Để sẵn sàng cho khoảnh khắc đó, tôi sẽ đề xuất những điều sau:

  1. Sử dụng ViewEncapsulation.None một cách khôn ngoan. Điều này được dịch là chỉ dành cho những thành phần cần truy cập các thành phần sâu hơn.
@Component({
      selector: 'app-example',
      templateUrl: './example.component.html',
      styleUrls: ['./example.component.scss'],
      encapsulation: ViewEncapsulation.None
    })
  1. Bây giờ, để tránh va chạm và sự kỳ lạ của CSS, bạn nên (theo quy tắc) luôn bao bọc mẫu thành phần của bạn bằng một lớp. Vì vậy, example.component.html sẽ giống như sau:
<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. Một lần nữa, theo quy tắc, dòng đầu tiên của mỗi tệp SCSS sẽ nhắm mục tiêu vùng chứa thành phần. Vì không có Encapsulation nên bạn có thể sửa đổi thành phần của bên thứ ba bằng cách nhắm mục tiêu các lớp của chúng. Điều đó nói rằng, example.component.scss sẽ giống như:
.app-example-container {
/* All the CSS code goes here */
.mat-tab-group .mat-tab-label {color: red;}
}

2

Đây không phải là sự thay thế chung cho :: ng-deep, nhưng dành cho trường hợp sử dụng được tác giả câu hỏi mô tả:

Trong trường hợp đặc biệt khi bạn muốn tạo kiểu cho phần tử được chèn bởi bộ định tuyến-đầu ra, có một giải pháp thanh lịch là sử dụng bộ chọn lân cận liền kề trong CSS:

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

Điều này sẽ áp dụng cho tất cả các phần tử là hàng xóm trực tiếp của bộ định tuyến-ổ cắm.

Đọc thêm:
https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_combinator
https://angular.io/guide/router#router-outlet


1
Tôi không khuyên bạn nên sử dụng bộ chọn này. Điều này có vẻ như bạn đang mở ra một cơn ác mộng về va chạm, đặc biệt là khi ứng dụng của bạn phát triển. Trên hết, bộ chọn * thực sự là bộ chọn chậm nhất duy nhất trong sự tồn tại của CSS.
dudewad 20/02/19

@dudewad trong khi * selector là bộ chọn chậm nhất, nó chỉ được áp dụng cho người anh em tiếp theo (+), không phải toàn bộ chuỗi / cây, vì vậy nó chỉ tạo ra sự khác biệt trên danh nghĩa.
Erik Philips

@ErikPhilips Bộ chọn CSS được phân tích cú pháp từ phải sang trái, vì vậy đây thực sự là trường hợp xấu nhất.
dudewad

@dudewad Tôi nghĩ chúng ta đang thiếu thứ gì đó. *là trường hợp xấu nhất theo sau element *nhưng element + *không ở đâu gần hai trường hợp đầu tiên.
Erik Philips

Tôi không biết ... Tôi chưa thử nghiệm nó, điều này chỉ dựa trên những gì tôi biết về cách trình phân tích cú pháp CSS thực hiện công việc của họ.
dudewad

1

Để tránh thay đổi cách đóng gói mặc định, tôi đã viết một trình trợ giúp nối các kiểu chung cho thành phần:

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

kết quả:

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

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.