關(guān)于Angular樣式封裝

引導(dǎo)

這是一個(gè)很簡(jiǎn)單的話(huà)題厌衔,但是你很難在搜索到一篇比較完整的介紹它的文章,或者說(shuō)單純的告訴你 ViewEncapsulation 的用法而已赡突,這在實(shí)際項(xiàng)目中遠(yuǎn)遠(yuǎn)不夠的紧索。

一袁辈、封裝模式

分別為:

  • Native 原先瀏覽器Shadow DOM行為。
  • Emulated 仿真模式珠漂,通過(guò)Angular來(lái)模擬類(lèi)似Shadow DOM的行為晚缩。
  • None 無(wú)任何封裝行為尾膊。

以上三種模式唯一的區(qū)別在于Shadow DOM,當(dāng)然其作用是讓組件的樣式只進(jìn)不出荞彼,換言之即組件內(nèi)的樣式不會(huì)影響到外部組件冈敛。有關(guān)于Shadow DOM更多的細(xì)節(jié)不在這里討論。

三者的表現(xiàn)形式

假定使用以下代碼:

@Component({
  template: `<h1>test</h1>`,
  styles: [`h1 { color: #f50; }`],
  encapsulation: ViewEncapsulation.Native
})

在不同模式下產(chǎn)生的HTML&CSS風(fēng)格都不盡相同鸣皂,了解這些不一樣尤為重要抓谴。它們分別為:

Native:

#shadow-root (open)
    <style>h1 { color: #f50; }</style>
    <h1>test</h1>

Emulated:

<style>h1[_ngcontent-c0] { color: #f50; }</style>
<h1 _ngcontent-c0>test</h1>

None:

<style>h1 { color: #f50; }</style>
<h1>test</h1>

Native & None 在內(nèi)容是一樣的,但其后者會(huì)影響至其他外部組件的 h1 元素寞缝。

二癌压、組件樣式

組件樣式的封裝模式取決于我們對(duì) encapsulation 的配置,例如上面的示例荆陆。當(dāng)然你可以了在 main.ts 時(shí)為所有組件統(tǒng)一設(shè)定一種行的模式滩届,例如:

platformBrowserDynamic().bootstrapModule(AppModule, {
  defaultEncapsulation: ViewEncapsulation.None
})

雖然三種模式都有不同的風(fēng)格,但對(duì)于一個(gè)組件而言慎宾,如果沒(méi)有一很合理的使用風(fēng)格在實(shí)際項(xiàng)目中會(huì)讓我們很頭疼丐吓,特別是當(dāng)項(xiàng)目中使用第三方組件庫(kù)(例如:ngx-bootstrap浅悉、ng-zorro-antd趟据、material2 等)時(shí),有時(shí)很容易受組件庫(kù)的影響抑或需要讓組件庫(kù)與業(yè)務(wù)組件樣式做一些微調(diào)時(shí)术健,了解一些細(xì)節(jié)非常重要汹碱。

例如一個(gè)用于渲染頁(yè)面標(biāo)頭名曰:app-header 組件,其中 <nz-breadcrumb> 面包屑 默認(rèn)情況下它會(huì)對(duì)最后一項(xiàng)進(jìn)行加粗荞估,但假設(shè)這不是我們希望的咳促,而應(yīng)該是一個(gè)不加粗和其他項(xiàng)一樣的文本:

<nz-breadcrumb>
  <nz-breadcrumb-item>Home</nz-breadcrumb-item>
  <nz-breadcrumb-item>Detail</nz-breadcrumb-item>
</nz-breadcrumb>

最終生成的HTML是這樣子:

<nz-breadcrumb _ngcontent-c1="" class="ant-breadcrumb">
    <nz-breadcrumb-item _ngcontent-c1="">
    <span class="ant-breadcrumb-link">
      Home
    </span>
    <span class="ant-breadcrumb-separator">/</span></nz-breadcrumb-item>
    <nz-breadcrumb-item _ngcontent-c1="">
    <span class="ant-breadcrumb-link">
      Detail
    </span>
    <span class="ant-breadcrumb-separator">/</span></nz-breadcrumb-item>
  </nz-breadcrumb>

倘若你不假思索的在 app-header 組件的 styles 屬性中加上:

.ant-breadcrumb-link {
    font-weight: normal;
}

正如你期望的那樣,可能不一定會(huì)有你想要的結(jié)果勘伺,亦或的結(jié)果可能會(huì)存在隱患跪腹。前面我說(shuō)過(guò)三種模式唯一的區(qū)別在于Shadow DOM,因此說(shuō)白了是兩種不同的結(jié)果飞醉。

若組件設(shè)定為 None 模式冲茸,而會(huì)生效,但只要 app-header 組件出現(xiàn)過(guò)一次在未來(lái)所有即使不再使用 app-header 組件的情況下所有的面包屑的最后一項(xiàng)都是是不加粗的缅帘,這便是我說(shuō)的隱患轴术。

反之,對(duì)于 Shadow 行為钦无,它會(huì)為 nz-breadcrumb 創(chuàng)建一個(gè)額外的屬性 _ngcontent-c1 來(lái)標(biāo)識(shí)(不管是 Native逗栽、Emulated 本質(zhì)是一樣的)所設(shè)定的樣式僅限于 app-header 組件當(dāng)中。而 Angular 中即采用 :host 來(lái)表示組件自身失暂,所以前面的CSS樣式應(yīng)該變成這樣:

:host .ant-breadcrumb-link {
    font-weight: normal;
}

最后生成的樣式會(huì)變成這樣:

[_nghost-c1] .ant-breadcrumb-link[_ngcontent-c1] {
  font-weight: normal;
}

我認(rèn)為我們沒(méi)有必要去理解生成的標(biāo)識(shí)符是怎么樣彼宠,只需要知道 :host 表示組件自身鳄虱。

然而我們會(huì)發(fā)現(xiàn),對(duì)于第三方組件 nz-breadcrumb 組件而言凭峡,.ant-breadcrumb-link 是其組件內(nèi)部某個(gè)HTML元素的 class 而已贝或,且它有自己的一套組件封裝規(guī)則。但我們生成的CSS中包括了一個(gè)奇怪的字符 [_ngcontent-c1]溃论,最終導(dǎo)致 app-header 組件樣式無(wú)法改變第三方組件 nz-breadcrumb 組件內(nèi)容的樣式圈澈。

這是很合理的,我的領(lǐng)地不可侵犯按价,Angular 組件本身即是 Web Component 標(biāo)準(zhǔn)的具體實(shí)現(xiàn)惭适。

難道我們沒(méi)有辦法侵犯第三方組件了嗎?好在 Angular 提供了一種對(duì)未來(lái)工具更好兼容性的命令 ::ng-deep 來(lái)強(qiáng)制樣式允許侵入子組件楼镐。

:host ::ng-deep .ant-breadcrumb-link {
  font-weight: normal;
}

生成的CSS會(huì)是這樣:

[_nghost-c1] .ant-breadcrumb-link {
  font-weight: normal;
}

最終這個(gè)不加粗的效果只會(huì)在 app-header 組件內(nèi)部有效癞志。

總結(jié)

熟悉 :host::ng-deep 組合用法對(duì)組件樣式的構(gòu)建很關(guān)鍵框产,Angular 組件有自己的業(yè)務(wù)邏輯凄杯、樣式、HTML模板它們是構(gòu)建一個(gè) Web Component 的基礎(chǔ)技術(shù)核心秉宿。

希望此篇能幫助大家更好理解組件樣式戒突。

Happy coding!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市描睦,隨后出現(xiàn)的幾起案子膊存,更是在濱河造成了極大的恐慌,老刑警劉巖忱叭,帶你破解...
    沈念sama閱讀 222,627評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件隔崎,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡韵丑,警方通過(guò)查閱死者的電腦和手機(jī)爵卒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)撵彻,“玉大人钓株,你說(shuō)我怎么就攤上這事∏Э担” “怎么了享幽?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,346評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)拾弃。 經(jīng)常有香客問(wèn)我值桩,道長(zhǎng),這世上最難降的妖魔是什么豪椿? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,097評(píng)論 1 300
  • 正文 為了忘掉前任奔坟,我火速辦了婚禮携栋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘咳秉。我一直安慰自己婉支,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,100評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布澜建。 她就那樣靜靜地躺著向挖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪炕舵。 梳的紋絲不亂的頭發(fā)上何之,一...
    開(kāi)封第一講書(shū)人閱讀 52,696評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音咽筋,去河邊找鬼溶推。 笑死,一個(gè)胖子當(dāng)著我的面吹牛奸攻,可吹牛的內(nèi)容都是我干的蒜危。 我是一名探鬼主播,決...
    沈念sama閱讀 41,165評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼睹耐,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼辐赞!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起疏橄,我...
    開(kāi)封第一講書(shū)人閱讀 40,108評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤占拍,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后捎迫,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,646評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡表牢,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,709評(píng)論 3 342
  • 正文 我和宋清朗相戀三年窄绒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片崔兴。...
    茶點(diǎn)故事閱讀 40,861評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡彰导,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出敲茄,到底是詐尸還是另有隱情位谋,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布堰燎,位于F島的核電站掏父,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏秆剪。R本人自食惡果不足惜赊淑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,196評(píng)論 3 336
  • 文/蒙蒙 一爵政、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧陶缺,春花似錦钾挟、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,698評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至苫费,卻和暖如春蛛砰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背黍衙。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,804評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工泥畅, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人琅翻。 一個(gè)月前我還...
    沈念sama閱讀 49,287評(píng)論 3 379
  • 正文 我出身青樓位仁,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親方椎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子聂抢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,860評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,323評(píng)論 25 707
  • 前言 說(shuō)起來(lái)ViewEncapsulation,首先要從Angular寫(xiě)component的入口說(shuō)起, 我們來(lái)看一...
    lolivialucky閱讀 1,579評(píng)論 0 2
  • 在介紹 ViewEncapsulation 之前棠众,我們先來(lái)介紹一下 Web Components 標(biāo)準(zhǔn)琳疏。 Web ...
    semlinker閱讀 2,944評(píng)論 0 2
  • 現(xiàn)在社會(huì)變化越來(lái)越快,是因?yàn)樯鐣?huì)使用的工具與過(guò)去進(jìn)化史上所有的工具都不同闸拿。舊石器空盼、新石器、農(nóng)業(yè)新荤、工業(yè)等等各個(gè)時(shí)代揽趾,...
    lhw8432037閱讀 154評(píng)論 0 0
  • 現(xiàn)在是資訊的時(shí)代,我們不再能用舊時(shí)代“單行道”的思想模式苛骨。如果你不能“一時(shí)多用”篱瞎、“一目十行”,甚至利用每個(gè)自覺(jué)與...
    做自己的CEO閱讀 1,192評(píng)論 1 5