ใช้อย่างไรและที่ไหน :: ng-deep?


95

ฉันยังใหม่กับ Angular 4 ดังนั้นใครก็ได้โปรดอธิบายวิธีใช้และสถานที่ที่จะใช้ ::ng-deepใน Angular 4 ได้บ้าง

อันที่จริงฉันต้องการเขียนทับคุณสมบัติ CSS บางส่วนของส่วนประกอบลูกจากส่วนประกอบหลัก นอกจากนี้ยังรองรับ IE11?


ตั้งแต่/deep/และ::ng-deepมีทั้งที่เลิกใช้ผมขอแนะนำให้คุณใช้ Alook คำตอบนี้stackoverflow.com/a/49308475/2275011และแสดงความคิดเห็นสำหรับรายละเอียดเพิ่มเติมและการแก้ปัญหา
Ferie

คำตอบ:


99

โดยปกติแล้ว /deep/ “shadow-piercing”Combinator สามารถใช้เพื่อบังคับสไตล์ลงไปchild componentsได้ ตัวเลือกนี้มีนามแฝง >>> และตอนนี้มีอีกชื่อหนึ่งว่า :: ng-deep

เนื่องจาก/deep/ combinatorเลิกใช้งานแล้วขอแนะนำให้ใช้::ng-deep

ตัวอย่างเช่น:

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

และ css

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

จะถูกนำไปใช้กับส่วนประกอบย่อย


รองรับ IE11 หรือไม่
Jeyabalan Thavamani

2
Angular ทำการแยกวิเคราะห์ดังนั้นคุณไม่จำเป็นต้องกังวลเกี่ยวกับความเข้ากันได้
Simon_Weaver

มีไว้สำหรับส่วนประกอบลูกเท่านั้นหรือไม่? อย่างที่ฉันจำได้และอย่างที่ฉันเห็นในความคิดเห็นอื่นมันยังสำหรับองค์ประกอบ Dom ภายนอก
yaya

ฉันสามารถยืนยันได้ว่ามันเป็นส่วนประกอบหลักเช่นกัน ... เพิ่งมีกรณีและรู้สึกรำคาญใจ
Shadoweb

74

การใช้งาน

::ng-deep, >>>และ/deep/ห่อหุ้มมุมมองปิดการใช้งานสำหรับกฎ CSS เฉพาะในคำอื่น ๆ ก็ช่วยให้คุณเข้าถึงองค์ประกอบ DOM ซึ่งไม่ได้อยู่ในองค์ประกอบของ HTML ตัวอย่างเช่นหากคุณใช้ Angular Material (หรือไลบรารีของบุคคลที่สามอื่น ๆ เช่นนี้) องค์ประกอบที่สร้างขึ้นบางส่วนอยู่นอกพื้นที่ของส่วนประกอบของคุณ (เช่นกล่องโต้ตอบ ) และคุณไม่สามารถเข้าถึงองค์ประกอบเหล่านั้นได้โดยตรงหรือใช้ CSS ปกติ ทาง. หากคุณต้องการเปลี่ยนรูปแบบขององค์ประกอบเหล่านั้นคุณสามารถใช้สิ่งใดสิ่งหนึ่งจากสามสิ่งเหล่านี้ตัวอย่างเช่น

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

ในตอนนี้ทีม Angular ขอแนะนำให้ทำการปรับแต่งแบบ "ลึก"ด้วยการห่อหุ้มมุมมองEMULATEDเท่านั้น

การเลิกจ้าง

การปรับแต่งแบบ "ลึก"ก็เลิกใช้งานไปแล้วเช่นกันแต่ตอนนี้ก็ยังใช้งานได้เนื่องจาก Angular ให้การสนับสนุนก่อนการประมวลผล (อย่าเพิ่งรีบปฏิเสธ::ng-deepในวันนี้ลองดูแนวทางการเลิกใช้งานก่อน)

อย่างไรก็ตามก่อนที่จะทำตามวิธีนี้ฉันขอแนะนำให้คุณดูที่การปิดใช้งานวิธีการห่อหุ้มมุมมอง (ซึ่งไม่เหมาะเช่นกันมันทำให้สไตล์ของคุณรั่วไหลไปสู่ส่วนประกอบอื่น ๆ ) แต่ในบางกรณีก็เป็นวิธีที่ดีกว่า หากคุณตัดสินใจที่จะปิดใช้งานการห่อหุ้มมุมมองขอแนะนำอย่างยิ่งให้ใช้คลาสเฉพาะเพื่อหลีกเลี่ยงการตัดกันของกฎ CSS และสุดท้ายหลีกเลี่ยงความยุ่งเหยิงในสไตล์ชีตของคุณ มันง่ายมากที่จะปิดการใช้งานใน.tsไฟล์ของคอมโพเนนต์:

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

คุณสามารถค้นหาข้อมูลเพิ่มเติมเกี่ยวกับการห่อหุ้มมุมมองในนี้บทความ


3
การปิดใช้งานการห่อหุ้มมุมมองจะใช้ CSS ทั้งหมดในคอมโพเนนต์ของคุณทั่วโลก
Vedran

19
อย่าใช้ViewEncapsulation.None! มันจะสร้างความเสียหายอย่างมากโดยการทำให้รูปแบบเหล่านั้นรั่วไหลไปสู่ส่วนประกอบอื่น ๆ
Alex Klaus

1
@AlexKlaus เห็นด้วยนั่นคือเหตุผลที่ฉันพูดถึงในคำตอบว่ามันไม่เหมาะ อันที่จริงฉันใช้เพียงครั้งเดียวเพื่อใช้รูปแบบที่ทำซ้ำได้ร่วมกันกับส่วนประกอบ Angular Material หากคุณพยายามปิดใช้งานการห่อหุ้มคุณอาจจะยุ่งเหยิงในบางจุด เป็นสิ่งที่ดีที่จะรู้เกี่ยวกับตัวเลือกนี้ แต่อย่าใช้ในขณะที่คุณไม่แน่ใจว่าต้องการสิ่งนี้จริงๆ
Commercial Suicide

36

ฉันจะเน้นความสำคัญของการ จำกัด::ng-deepเฉพาะชายด์ของส่วนประกอบโดยกำหนดให้พาเรนต์เป็นคลาส css ที่ห่อหุ้ม

เพื่อให้ใช้งานได้สิ่งสำคัญคือต้องใช้::ng-deepafter the parent ไม่ใช่ก่อนหน้านี้มิฉะนั้นจะใช้กับคลาสทั้งหมดที่มีชื่อเดียวกันในขณะที่โหลดส่วนประกอบ

ส่วนประกอบ css:

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

แม่แบบส่วนประกอบ:

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

ผลลัพธ์ (สร้างเชิงมุม) css:

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

แก้ไข:

คุณสามารถบรรลุพฤติกรรมเดียวกันได้โดยใช้:hostคำสำคัญแทนการสร้างคลาส css ใหม่

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

7
ผู้ชายคำตอบของคุณmy-component ::ng-deep...ช่วยวันของฉัน ฉันใช้เวลาทั้งวันในการพยายามใช้สไตล์สำหรับส่วนประกอบของฉันด้วย ng-deep และลบล้างส่วนประกอบทั้งหมดของฉันจากแอปพลิเคชันทั้งหมดของฉัน
Cristiano Bombazar

2
สิ่งที่น่าสังเกต: "ในการกำหนดขอบเขตสไตล์ที่ระบุให้กับองค์ประกอบปัจจุบันและรุ่นต่อ ๆ ไปทั้งหมด [แต่ไม่ใช่แบบทั่วโลก] อย่าลืมใส่: host selector ก่อน :: ng-deep" From: angular.io/guide/component-styles
StvnBrkdll

1
@CristianoBombazar - คุณจะได้รับพฤติกรรมเดียวกันกับ:hostคำหลัก - เพิ่มบันทึกคำตอบเพื่อความชัดเจน
Vedran

25

ตรวจสอบให้แน่ใจว่าไม่พลาดคำอธิบายของ:host-contextซึ่งเป็นตรงเหนือ::ng-deepในคู่มือเชิงมุม: https://angular.io/guide/component-styles ฉันพลาดมาจนถึงตอนนี้และหวังว่าจะได้เห็นเร็ว ๆ นี้

::ng-deepมักเป็นสิ่งจำเป็นเมื่อคุณไม่ได้เขียนส่วนประกอบและไม่มีสิทธิ์เข้าถึงแหล่งที่มา แต่:host-contextอาจเป็นตัวเลือกที่มีประโยชน์มากเมื่อคุณทำ

ตัวอย่างเช่นฉันมี<h1>ส่วนหัวสีดำภายในส่วนประกอบที่ฉันออกแบบและฉันต้องการความสามารถในการเปลี่ยนเป็นสีขาวเมื่อแสดงบนพื้นหลังที่มีธีมสีเข้ม

หากฉันไม่สามารถเข้าถึงแหล่งที่มาฉันอาจต้องทำสิ่งนี้ใน css สำหรับผู้ปกครอง:

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

แต่:host-contextคุณสามารถทำสิ่งนี้ภายในส่วนประกอบแทนได้

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

สิ่งนี้จะดูที่ใดก็ได้ในห่วงโซ่ส่วนประกอบสำหรับ.theme-darkและใช้ css กับ h1 หากพบ นี่เป็นทางเลือกที่ดีในการพึ่งพามากเกินไป::ng-deepซึ่งในขณะที่ความจำเป็นมักจะเป็นการต่อต้านรูปแบบ

ในกรณีนี้&จะถูกแทนที่ด้วยh1(นั่นคือวิธีการทำงานของ sass / scss) เพื่อให้คุณสามารถกำหนด css 'ปกติ' และธีม / ทางเลือกที่อยู่ติดกันซึ่งมีประโยชน์มาก

:ระวังจะได้รับหมายเลขที่ถูกต้องของ เพราะ::ng-deepมีสองและ:host-contextหนึ่งเดียว


คุณยังสามารถใช้:host(.theme-dark)หากคุณไม่ต้องการรับช่วงtheme-darkจากองค์ประกอบหลักใด ๆ ทั้งหมดนี้จะขึ้นอยู่กับการออกแบบ css ของไซต์ของคุณ แอตทริบิวต์ยังมีประโยชน์มากและสามารถรวมเข้าด้วยกันได้อย่างซับซ้อนใน css เพียงอย่างเดียว:host([theme='dark']:not([dayofweek='tuesday'))
Simon_Weaver

โปรดทราบว่าสิ่งนี้เป็นไปตามกฎ css ปกติดังนั้นหากคุณมีส่วนประกอบตามที่อธิบายไว้ข้างต้น (พร้อมโฮสต์บริบท css) ภายในคอนเทนเนอร์ที่มี.theme-lightคลาสสิ่งนี้จะซ้อนอยู่ภายในคอนเทนเนอร์โดย.theme-darkจะยังคงรับtheme-darkและใช้ css. แต่นี่เป็นวิธีแก้ปัญหาที่ยอดเยี่ยมสำหรับคลาสประเภท "modernizr" หรือหากคุณมีชุดรูปแบบทั่วโลกเพียงครั้งเดียว
Simon_Weaver

ฉันสามารถใช้: host-context แทน :: ng-deep ได้หรือไม่
วน

@eddy ตอนนี้ฉันง่วงเกินไปที่จะคิดอย่างเต็มที่ แต่บริบทของโฮสต์นั้นเกือบจะเหมือนกับ ng-deep แต่จะขึ้นต้นไม้ DOM แทนที่จะลง ดังนั้นจึงไม่เทียบเท่ากันอย่างแน่นอน แต่คุณทำได้
Simon_Weaver

2

เพียงแค่อัปเดต:

คุณควรใช้::ng-deepแทน/deep/สิ่งที่ดูเหมือนจะเลิกใช้แล้ว

ตามเอกสาร:

Combinator ลูกหลานที่เจาะด้วยเงาถูกเลิกใช้งานและการสนับสนุนจะถูกลบออกจากเบราว์เซอร์และเครื่องมือหลัก ๆ ดังนั้นเราจึงวางแผนที่จะลดการสนับสนุนใน Angular (สำหรับทั้ง 3 ของ / deep /, >>> และ :: ng-deep) ถึงเวลานั้น :: ควรเลือก ng-deep เพื่อให้เข้ากันได้กับเครื่องมือที่กว้างขึ้น

คุณสามารถค้นหาได้ที่นี่


5
ในข้อความนี้ระบุไว้อย่างชัดเจนว่า :: ng-deep ก็เลิกใช้งานเช่นกัน: "เราวางแผนที่จะลดการสนับสนุนใน Angular (สำหรับทั้ง 3 ของ / deep /, >>> และ :: ng-deep)"
adripanico

-2

ใช้ :: ng-deep ด้วยความระมัดระวัง ฉันใช้มันตลอดทั้งแอปเพื่อตั้งค่าสีของแถบเครื่องมือการออกแบบวัสดุเป็นสีที่แตกต่างกันในแอปของฉันเพียงเพื่อจะพบว่าเมื่อแอปกำลังทดสอบสีของแถบเครื่องมือซึ่งกันและกัน มาดูกันว่าเป็นเพราะสไตล์เหล่านี้กลายเป็นสากลโปรดดูบทความนี้ นี่คือโซลูชันโค้ดที่ใช้งานได้ซึ่งไม่ตกอยู่ในส่วนประกอบอื่น ๆ

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

}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.