目錄
css 選擇器
angular 樣式隔離實作機制
::ng-deep
:host
总结
首頁 web前端 js教程 一起聊聊angular的樣式隔離實作機制

一起聊聊angular的樣式隔離實作機制

Nov 16, 2021 pm 06:33 PM
angular

Angular是怎麼進行樣式隔離的?以下這篇文章就來和大家一起聊聊angular的樣式隔離實作機制,希望對大家有幫助!

一起聊聊angular的樣式隔離實作機制

angular 以元件為基本單位。我們編寫一個一個的元件,再將這些元件組合為一顆組件樹。但是在開發的過程中,經常需要在父元件中覆蓋子元件的樣式。例如現在我們有一個parent 組件和child 組件,child 組件裡面有一個span,span 的字體是紅色。 【相關教學推薦:《angular教學》】  

如下:

//child.componet.html
<span class="child-span">child span</span>
//child.component.scss
.child-span {
  color: red;
}
登入後複製
登入後複製

如果現在,parent 元件想要child 元件中span 的內容變成綠色。可以使用以下的方式

//parent.component.scss
app-child {
  ::ng-deep {
    .child-span {
      color: green;
    }
  }
}
登入後複製
登入後複製

在parent 元件中,使用angular 提供的::ng-deep 關鍵字進行樣式的覆寫。

現在我們修改一下child 元件的內容,在span 外面加上一層div,畢竟現實中的元件肯定不會只有一層這麼簡單。

//child.componet.html
<div class="child-div">
  <span class="child-span">child span</span>
</div>
//child.component.scss
.child-div {
  .child-span {
    color: red;
  }
}
登入後複製
登入後複製

這時候,我們會發現child 元件中span 的內容又變回了紅色,之前parent 元件對其的覆蓋並沒有生效。

::ng-deep 為什麼會失效呢?或者說,::ng-deep 會在什麼時候有效?什麼時候失效?更進一步說,angular 中元件和元件之間的樣式隔離是怎麼做到的呢?

css 選擇器

css 中提供了元素選擇器,id 選擇器,class 選擇器以及屬性選擇器

對於angular 的樣式隔離的問題,比較重要的就是屬性選擇器。 在屬性選擇器中,透過為元素添加任意一個屬性,可以準確地選取這個元素。 比如說,

a[target] {
    background-color:yellow;
}
登入後複製

透過上面的選擇器,我們可以選取所有帶有target屬性的a元素。

另外一個是後代選擇器

在css 中,後位選擇器會選擇指定元素的所有後代元素。 例如,

[attr] span {
    color: green;
}
登入後複製

這個選擇器會先選取帶有attr 屬性的元素,然後選取這個元素的所有後代span 元素。

有了css 屬性選擇器後位選擇器,就有了所有需要完成元件樣式隔離的工具。 angular 中元件的樣式隔離與::ng-deep 完全基於這兩個內容。

angular 樣式隔離實作機制

我們現在回到之前的angular元件 child 元件的內容為

//child.componet.html
<span class="child-span">child span</span>
//child.component.scss
.child-span {
  color: red;
}
登入後複製
登入後複製

parent 元件的內容為

//parent.component.html
<app-child></app-child>
登入後複製

上面兩個元件經過angular 處理以後,產生的html 內容如下

一起聊聊angular的樣式隔離實作機制

可以看到,parent 元件上面多了_ngcontent-mye-c13_nghost-mye-c12 兩個屬性,而child 元件上面多了_ngcontent- mye-c12_nghost-mye-c11 兩個屬性,child 元件下的span 標籤,增加了_nghost-mye-c11 屬性。

對於scss 文件,經過angular 的處理以後,在child 元件中的.child-span 類,變成了.child-span[_nghost-mye-c11]

一起聊聊angular的樣式隔離實作機制

透過這些內容我們就可以看出來angular 的樣式隔離就是利用屬性選擇器完成的。

_nghost-mye-c11 這個屬性只會出現在child 元件中。在child.component.scss 中的.child-span類別變成了.child-span[_nghost-mye-c11],根據先前提到的屬性選擇器的機制,.child-span 只會對child 元件的內容生效。

如果在parent 元件內部也寫一個.child-span類別選擇器,那麼產生的類別選擇器就會是.child-span[_nghost-mye-c12 ]。而_nghost-mye-c12 這個屬性是屬於parent 元件的,所以這個.child-span 類別只會對parent 元件的內容生效。並不會影響到child 元件,樣式的隔離也就完成了。

::ng-deep

那為什麼透過::ng-deep 可以在parent 元件裡面,覆蓋child 元件中的內容呢?

//parent.component.scss
app-child {
  ::ng-deep {
    .child-span {
      color: green;
    }
  }
}
登入後複製
登入後複製

上面的内容通过angular 处理以后,生成的内容为app-child[_nghost-mye-c12] .child_span。位于::ng-deep 后面的类,去掉了自动添加的属性,这时候根据css 的后代选择器机制。app-child[_nghost-mye-c12] .child_span会选中child 组件下面的所有带有.child_span 类的标签,而且根据优先级计算,app-child[_nghost-mye-c12] .child_span 高于child 组件生成的.child_span[_nghost-mye-c11] ,于是child 组件中的样式就被覆盖掉了。

那为什么有时候::ng-deep不能够覆盖掉呢?比如,当child 组件代码如下的时候

//child.componet.html
<div class="child-div">
  <span class="child-span">child span</span>
</div>
//child.component.scss
.child-div {
  .child-span {
    color: red;
  }
}
登入後複製
登入後複製

这时候即使我们发现child 组件中span 的颜色依旧是红色。

实际上原因也不复杂,检查angular 生成的样式文件后,我们可以发现,之所以没有把覆盖掉,纯粹是因为css 选择器优先级的问题。child 组件生成的样式.child-div[_nghost-mye-c11] .child-span[_nghost-mye-c11] 优先级高于parent 组件生成的样式app-child[_nghost-mye-c12] .child。于是,我们看到的效果就是parent 组件中的::ng-deep 没有生效,一种比较快捷的做法是直接在parent 组件的样式后面加上!important。但是由于!important 权重太高的原因,并不是很推荐。歪个楼,在发现angular ::ng-deep 失效的原因之前,很遗憾,项目之前很多地方的都有这种用法。

另一个方法就是,既然是因为优先级不够,那么提高parent 组件生成的样式的优先级就可以了。 修改parent 组件的代码为

:host {
  app-child {
    ::ng-deep {
      .child-div {
        .child-span {
          color: green;
        }
      }
    }
  }
}
登入後複製

这时候,parent 组件生成的样式[_nghost-mye-c12] app-child[_nghost-mye-c12] .child-div .child-span 优先级高于child 组件生成的样式.child-div[_nghost-mye-c11] .child-span[_nghost-mye-c11] ,child 组件中span 的颜色也就变绿了。

这里我们使用了:host 关键字,接下来,我们简单看看它的作用。

:host

上个小结中,parent 组件生成的样式是[_nghost-mye-c12] app-child[_nghost-mye-c12] .child-div .child-span,如果去掉:host,就会发现,生成的样式变成了app-child[_nghost-mye-c12] .child-div .child-span。所以:host 关键字只是给生成的样式,加上了parent 组件属性字段而已。

那这个:host有什么用呢?

常见的作用有两个。

一个就是选择当前的组件标签,在angular 中,我们自定义的组件,比如这里的parent 组件app-parent 和child 组件app-child 最后都是会渲染到生成的html 文档上的。如果需要选中这些标签,就可以使用:host 关键字。

另一个作用还是隔离样式,将class 类写在:host 内部,这个类无论如何也是不可能泄漏到全局去的。实际上,通过前面的内容分析可以发现,不写在:host 里面,也不会泄漏到全局。但是如果出现了以下的情况

//some.component.scss
::ng-deep {
    .random-class {
        xxxx
    }
}
登入後複製

这个类经过angular 处理以后,最后会变为

.random-class {
    xxxx
}
登入後複製

random-class 将会对全局造成影响。

但是如果把它包裹在:host 内部,哪怕使用了::ng-deep 关键字,最多也只会影响到这个组件的后代元素。 所以在angular 官方文档中有下面的一段话。

Applying the ::ng-deep pseudo-class to any CSS rule completely disables view-encapsulation for that rule. Any style with ::ng-deep applied becomes a global style. In order to scope the specified style to the current component and all its descendants, be sure to include the :host selector before ::ng-deep. If the ::ng-deep combinator is used without the :host pseudo-class selector, the style can bleed into other components.

总结

我们首先介绍了css 的属性选择器和后代选择器。通过分析angular 生成的html 和css 代码,发现angular 的样式隔离功能,完全是基于这两个内容实现的。接下来,分析了::ng-deep 有时候生效,有时候有不生效的原因。最后介绍了使用:host 关键字来完全避免样式泄漏到全局。

更多编程相关知识,请访问:编程视频!!

以上是一起聊聊angular的樣式隔離實作機制的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1672
14
CakePHP 教程
1428
52
Laravel 教程
1332
25
PHP教程
1277
29
C# 教程
1257
24
聊聊Angular中的元資料(Metadata)和裝飾器(Decorator) 聊聊Angular中的元資料(Metadata)和裝飾器(Decorator) Feb 28, 2022 am 11:10 AM

這篇文章繼續Angular的學習,帶大家了解Angular中的元數據和裝飾器,簡單了解一下他們的用法,希望對大家有幫助!

如何在Ubuntu 24.04上安裝Angular 如何在Ubuntu 24.04上安裝Angular Mar 23, 2024 pm 12:20 PM

Angular.js是一種可自由存取的JavaScript平台,用於建立動態應用程式。它允許您透過擴展HTML的語法作為模板語言,以快速、清晰地表示應用程式的各個方面。 Angular.js提供了一系列工具,可協助您編寫、更新和測試程式碼。此外,它還提供了許多功能,如路由和表單管理。本指南將討論在Ubuntu24上安裝Angular的方法。首先,您需要安裝Node.js。 Node.js是一個基於ChromeV8引擎的JavaScript運行環境,可讓您在伺服器端執行JavaScript程式碼。要在Ub

一文探究Angular中的服務端渲染(SSR) 一文探究Angular中的服務端渲染(SSR) Dec 27, 2022 pm 07:24 PM

你知道 Angular Universal 嗎?可以幫助網站提供更好的 SEO 支援哦!

淺析angular中怎麼使用monaco-editor 淺析angular中怎麼使用monaco-editor Oct 17, 2022 pm 08:04 PM

angular中怎麼使用monaco-editor?以下這篇文章記錄下最近的一次業務中用到的 m​​onaco-editor 在 angular 中的使用,希望對大家有幫助!

Angular + NG-ZORRO快速開發一個後台系統 Angular + NG-ZORRO快速開發一個後台系統 Apr 21, 2022 am 10:45 AM

這篇文章跟大家分享一個Angular實戰,了解一下angualr 結合 ng-zorro 如何快速開發一個後台系統,希望對大家有幫助!

angular學習之詳解狀態管理器NgRx angular學習之詳解狀態管理器NgRx May 25, 2022 am 11:01 AM

這篇文章帶大家深入了解angular的狀態管理器NgRx,介紹一下NgRx的使用方法,希望對大家有幫助!

如何使用PHP和Angular進行前端開發 如何使用PHP和Angular進行前端開發 May 11, 2023 pm 04:04 PM

隨著網路的快速發展,前端開發技術也不斷改進與迭代。 PHP和Angular是兩種廣泛應用於前端開發的技術。 PHP是一種伺服器端腳本語言,可以處理表單、產生動態頁面和管理存取權限等任務。而Angular是一種JavaScript的框架,可以用來開發單一頁面應用程式和建構元件化的網頁應用程式。本篇文章將介紹如何使用PHP和Angular進行前端開發,以及如何將它們

使用Angular和Node進行基於令牌的身份驗證 使用Angular和Node進行基於令牌的身份驗證 Sep 01, 2023 pm 02:01 PM

身份驗證是任何網路應用程式中最重要的部分之一。本教程討論基於令牌的身份驗證系統以及它們與傳統登入系統的差異。在本教程結束時,您將看到一個用Angular和Node.js編寫的完整工作演示。傳統身份驗證系統在繼續基於令牌的身份驗證系統之前,讓我們先來看看傳統的身份驗證系統。使用者在登入表單中提供使用者名稱和密碼,然後點擊登入。發出請求後,透過查詢資料庫在後端驗證使用者。如果請求有效,則使用從資料庫中獲取的使用者資訊建立會話,然後在回應頭中傳回會話訊息,以便將會話ID儲存在瀏覽器中。提供用於存取應用程式中受

See all articles