記一次小程序樣式優化重構

上週花了 3 天的時間和老大一塊兒重構了一下小程序的樣式開發,雖說在開發的過程當中遇到了一些問題,可是最終減小了很多樣式代碼,同時功能上也更增強大。進一步來講,若是在後面咱們的小程序用戶想要本身定製化主題,也能夠很快的實現。css

全局樣式開發

以前的小程序開發中,咱們全方面使用了 Component 構造小程序組件以及頁面(頁面也可使用 Component 構造器來編寫)。固然一方面是由於小程序 Component 的開發體驗很是好,擁有相似於 Vue mixin, watch 的 behaviorsobservers,比 Page 構造器強大了不少。另外一方面,對於業務較重的小程序來講, Component 也有性能優點。能夠參照 滴滴開源小程序框架Mpx 中的 Page與Component setData性能對照html

在開發過程當中,有不少樣式是能夠複用的。若是在以前開發中常用 Bootstrap 之類的 ui 庫,那麼你就會習慣使用這種庫的 utilities 類。可是默認狀況下,自定義組件的樣式只受到自定義組件 wxss 的影響。不會受到全局樣式 app.wxss 的影響。因此咱們只能經過增長 @import 語法來輔助各個組件進行開發。前端

@import "xxx.css";

若是你使用 CSS 預處理器來輔助小程序開發的話,可能就須要經過 gulp-insert 爲編譯出來的 wxss 文件前置添加該語句。請注意: 之因此 @import 須要前置,是由於 @import 語法會把引入的樣式按照導入的位置來生效,也就是說,按照 CSS 同等權重看前後的規則來講,若是把 @import 放在中間位置,前面位置定義的樣式可能會被 @import 給覆蓋掉。git

小程序全局樣式

固然,小程序基礎庫版本在 2.2.3 以上就支持了addGlobalClass 配置項,即在 Component 的 options 中設置 addGlobalClass: truegithub

Component({
  options: {
    addGlobalClass: true
  }
})

該配置項目表示頁面級別的 wxss 樣式將影響到自定義組件,但自定義組件 wxss 中指定的樣式不會影響頁面。也就是說咱們能夠用該配置替代以前的每一個組件的 @import。只要在 app.wxss 上導入 CSS 樣式便可,同時咱們能夠在頁面上對組件內部的樣式進行修改。不過須要說明的是: 該配置並不影響父子組件間的樣式。各個子組件只受到 app.wxss 和頁面的樣式的侵入。小程序開發基本上以頁面爲單位,因此這個配置是很是適合開發的。不過在以前的開發中並無在乎過這個配置。npm

組件樣式隔離

固然了,在後面的版本 2.6.5 中,微信小程序也提供了更爲詳細的隔離選項 styleIsolationjson

Component({
  options: {
    styleIsolation: 'isolated'
  }
})
  • isolated 表示啓用樣式隔離,在自定義組件內外,使用 class 指定的樣式將不會相互影響(通常狀況下的默認值)。
  • apply-shared 表示頁面 wxss 樣式將影響到自定義組件,但自定義組件 wxss 中指定的樣式不會影響頁面。
  • shared 表示頁面 wxss 樣式將影響到自定義組件,自定義組件 wxss 中指定的樣式也會影響頁面和其餘設置了 apply-sharedshared 的自定義組件。(這個選項在插件中不可用)。

styleIsolation 淺析

若是你們不想了解太多,只想使用的話, 簡短來講: gulp

你們在組件中直接使用 apply-shared,若是當前的 Component 構造器應用於頁面,那麼不要配置隔離選項便可。其他的隔離選項都是基本沒什麼用的。bootstrap

styleIsolation 詳解

isolated 等同於什麼都不幹,設置不設置通常沒有區別,因此能夠當該配置項目不存在。小程序

apply-shared 等同於addGlobalClass: true,也是最有用的配置項 。

shared 最複雜,在子組件設置了樣式,不但會影響自身和頁面(同時包括了其餘設置了apply-sharedshared 的自定義組件),同時呢,又會被頁面樣式和其餘設置了 shared 的組件樣式影響。在我使用該功能的過程當中,我認爲,這個配置項千萬不要在組件中去使用,除非你「瘋了」。

可是不介紹這個配置項目又不行,由於當你使用 Component 去構建頁面時候,該頁面的配置項目默認就是 shared。這是由於頁面又須要全局樣式,又須要影響其餘設置了apply-sharedshared 的自定義組件。

不過能夠放心的是: 小程序樣式隔離是以頁面爲單位,不會影響全局樣式,即便當前頁面你有組件使用了以 shared 影響了當前頁面。跳轉到下一個頁面中,不會出現問題。因此咱們基本上按照上面的設置便可。

針對於頁面級別的 Component 還有幾個額外的樣式隔離選項可用:

  • page-isolated 表示在這個頁面禁用 app.wxss ,同時,頁面的 wxss 不會影響到其餘自定義組件;
  • page-apply-shared 表示在這個頁面禁用 app.wxss ,同時,頁面 wxss 樣式不會影響到其餘自定義組件,但設爲 shared 的自定義組件會影響到頁面;
  • page-shared 表示在這個頁面禁用 app.wxss ,同時,頁面 wxss 樣式會影響到其餘設爲 apply-sharedshared 的自定義組件,也會受到設爲 shared 的自定義組件的影響。

基本上這些配置都會讓頁面上禁用 app.wxss,因此在開發中並不使用。你們若是有需求,能夠自行研究。

從小程序基礎庫版本 2.10.1 開始,也能夠在頁面或自定義組件的 json 文件中配置 styleIsolation (這樣就不需在 js 文件的 options 中再配置)。例如:

{
  "styleIsolation": "isolated"
}

其餘樣式配置功能

諸如 外部樣式類) 和 引用頁面或父組件的樣式) 這些功能,你們也可酌情學習使用。不過有了組件樣式隔離以後,這些功能可能就有些雞肋,我能夠直接經過頁面的樣式控制組件內部的樣式。並且外部樣式類功能須要父組件直接提供樣式,不會被 app.wxss 所影響。

在樣式隔離功能使用的狀況下,咱們能夠大幅度減小各個組件的代碼。而且讓整個小程序內部更加乾淨整潔,可重用性更高。同時咱們的主題色等全局配置均可以經過修改 app.wxss 來修改。

CSS var 定製主題

var 功能簡單描述

若是當年 CSS 預處理器變量對於我來講是開啓了新世界的大門,那麼 CSS 變量這個功能對於無疑就是晴天霹靂。

// 在 body 選擇器中聲明瞭兩個變量
body {
  --primary-color: #7F583F;
  --secondary-color: #F7EFD2;
}

/** 同一個 CSS 變量,能夠在多個選擇器內聲明。優先級高的會替換優先級低的 */
.a {
  --primary-color: #FFF;
  --secondary-color: #F4F4F4;
}

/** 使用 CSS 變量 */
.btn-primary {
  color: var(--primary-color)
}

在前端的領域中,標準的實現老是比社區的約定要慢的多,前端框架最喜歡的 $ 被 Sass 變量用掉了。而最經常使用的 @ 也被 Less 用掉了。官方爲了讓 CSS 變量也可以在 Sass 及 Less 中使用,無奈只能妥協的使用 --。

固然,咱們也能夠經過 JS 來操做 CSS 變量。如此,CSS 變量能夠動態的修改。

// 設置變量
document.body.style.setProperty('--primary', '#7F583F');

// 讀取變量
document.body.style.getPropertyValue('--primary').trim();
// '#7F583F'

// 刪除變量
document.body.style.removeProperty('--primary');

var 默認配置

事實上,var() 函數還可使用第二個參數,表示變量的默認值。若是該變量此前沒有定義,就會使用這個默認值。若是讓我來思考,我確定沒法想象出結合 Less 和 CSS 變量即可以實現小程序樣式的默認配置。這裏咱們參考了有讚的 Vant Weapp 的作法。有贊代碼 theme.less 以下所示:

// 先導入全部 less 變量
@import (reference) './var.less';

// 利用正則去替換變量
.theme(@property, @imp) {
  @{property}: e(replace(@imp, '@([^() ]+)', '@{$1}', 'ig'));
  @{property}: e(replace(@imp, '@([^() ]+)', 'var(--$1, @{$1})', 'ig'));
}

函數效果以下所示:

@import '../common/style/theme.less';

.van-button {
  // ... 其餘省略
  .theme(height, '@button-default-height');
  .theme(line-height, '@button-line-height');
  .theme(font-size, '@button-default-font-size');
}

// => 編譯以後

.van-button{
   // ... 其餘省略
  height:44px;
  height:var(--button-default-height,44px);
  line-height:20px;
  line-height:var(--button-line-height,20px);
  font-size:16px;
  font-size:var(--button-default-font-size,16px);
}

咱們能夠看到每調用一次 Less 函數將會被編譯成兩個屬性。第一個屬性的設定對於不支持 CSS 變量的設備能夠直接使用,若是當前設備支持 CSS 變量,則會使用 CSS 變量,可是因爲當前 css 變量未定義,就會使用變量的默認值。

通過這種函數的修改,咱們就能夠完成定製主題。詳細請參考 Vant Weapp 定製主題

// component.wxml
<van-button class="my-button">
  默認按鈕
</van-button>

// component.wxss

.my-button {
  --button-border-radius: 10px;
  --button-default-color: #f2f3f5;
}

你們可能有時候會想,這樣的話,不是有更多的代碼了嗎?其實未必,事實上咱們能夠直接直接在頁面內部定義變量樣式。其餘組件直接經過樣式隔離去使用頁面內的變量。固然了,事實上書寫的代碼多少,重點在於想要控制默認樣式的粒度大小。粒度越小,則須要在各個組件內部書寫的變量越多,粒度大,咱們也就沒必要考慮太多。

固然了,咱們能夠基於用戶機型提供默認和適合當前機型修改的的樣式配置,這樣的話。即便用戶想要本身定義,也不會出現樣式特別怪異的情況。

參考資料

小程序 組件模板和樣式

CSS 變量教程

Vant Weapp 樣式覆蓋

鼓勵一下

若是你以爲這篇文章不錯,但願能夠給與我一些鼓勵,在個人 github 博客下幫忙 star 一下。
博客地址

相關文章
相關標籤/搜索