騰訊 Web UI 解決方案 QMUI Web —— 探索與沉澱

做者簡介: 李浩成(Kayo),騰訊廣州研發部 UI 工程師。git

通過長時間的打磨迭代,QMUI Web 做爲騰訊廣研 QMUI 團隊的一個開源項目,正式發佈到 Tencent Github。QMUI Web 是一個 Web UI 的解決方案,從零開始,由編碼規範,到組件和工具方法的製做,再到工做流的整合,不斷在迭代,也不斷在優化,走過了很多的路。趁着發佈的機會,咱們正好回顧這一路的探索過程,分享其中的點滴,也但願能借此讓你們更瞭解 QMUI Web。github

背景

2014 年中,QMUI 團隊支持的主要項目是 QQ 郵箱,Web 端的郵箱是個龐大的項目,但其並無統一的 UI 基礎庫,多年的高速迭代使得項目的 UI 代碼變得混亂,各個模塊之間各自開發,除了在代碼層面表現出混亂和不可控以外,表現層面也並無很好地統一塊兒來。所以,項目急需一套統一的團隊編碼規範以及一個 UI 基礎庫。 剛好,這個時候 Sass 等 CSS 預處理器已經發展成熟,自動化工做流的工做模式也日趨完善,所以,咱們決定基於這些技術製做一套通用於不一樣項目的 Web UI 框架。框架的場景定位很明確:須要控制總體樣式,而且能夠適應頻繁迭代打磨的大型項目。因此,這套即將誕生的 Web UI 框架的特性也很明確:須要方便地控制項目的總體樣式,應對頻繁的界面變更,並保持項目質量穩健。 此後通過三年的發展,QMUI Web 最終發展爲包含編碼規範、樣式工具方法與樣式管理、內置工做流,配套的 GUI 桌面 App,以及擁有完整文檔的解決方案。gulp

設計理念

在製做框架的過程當中,咱們把框架須要的特性進行整理和思考,造成了一套對於該框架的設計理念,在這些設計理念之中,最核心的關鍵爲通用於多個項目高效迭代保持代碼穩健,框架的設計也遵循這三個核心點,體如今框架上,具體就是:瀏覽器

  • 框架和組件須要剝離業務。做爲 UI 框架,框架內整合的組件和樣式必須有能力剝離業務,才能跨項目使用。
  • 能輕易控制總體樣式。須要高效地迭代項目,樣式的總體控制必不可少。
  • 保持代碼穩健。

而具體到代碼層面,則能夠概括爲兩個方面:框架

  • Class-name 命名規範。
  • 基礎樣式配置與半封裝組件。

Class-name 命名規範

做爲一個 Web UI 框架,編寫代碼主要是 CSS 與 HTML,而提到 CSS 與 HTML 的編寫,首先要處理的是 Class-name 的命名,在過往的開發中,Class-name 的命名並無固定的規範,開發人員各自進行開發,一個項目通過長時間的迭代後,常常會遇到如命名衝突,命名混亂等問題,這使得項目的迭代變得笨重,也很差維護。所以,咱們須要一套具備以下特色的 Class-name 命名規範:工具

  • 命名有跡可循,容易編寫。
  • 避免命名衝突,包括內部多人協做命名衝突,以及外部庫引入時的被動污染。
  • 命名具備語義,能晰地描述整個頁面,方便理解上下文。

所以,最終 QMUI Web 制定了一套以命名空間爲核心的命名方式,這個命名方式主要由「命名空間」,「業務與組件的拆分」,「精確表達 View」三個部分構成。測試

命名空間

一個 QMUI Web Class-name 應該包含一個命名空間,也是 Class-name 的開頭,若是是業務,則以業務內容爲命名空間,若是是公共組件,則全局使用項目的名字(或縮寫)爲命名空間。如一個名爲 Demo 的項目,項目縮寫能夠是 dm,那麼該項目下的項目組件和公共類能夠這樣命名: dm_btn(按鈕)、dm_icon(圖標)、dm_ipt(輸入框)、dm_toolbar(工具欄)。 邏輯模塊命名以具體業務做爲前綴,如簡歷(resume)功能裏面的非公共組件部分,以 resume_ 做爲前綴(resume_modresume_textresume_list),我的信息(profile)頁面的非公共組件部分,則能夠以 profile_ 做爲前綴(profile_statgeprofile_stage_title)。 命名空間做爲一種基礎的隔離,把組件與業務,以及不一樣的業務之間的 Class-name 命名隔離開來,避免衝突,然後父子元素之間逐級展開編寫,保證了項目內多人協助不易衝突,同時命名帶有語義,也方便理解和閱讀。字體

image_1bouo6vnb1jsg1q31af418351e129.png-85.3kB

image_1bouo7q7t1lsi1f7kqkktsk1tn9m.png-61.8kB

業務與組件的拆分

接着,QMUI Web 中把項目的代碼劃分爲通用組件(跨項目的組件),項目全局組件(適用於某個具體項目),業務組件(適用於某個業務),以及業務邏輯代碼,這樣區分出4個顆粒度可使得代碼更容易被組織和複用,一個模塊隨着設計元素迭代,也能夠在這4個顆粒度之間進行迭代,從而使得模塊在迭代時會更加穩健。而 QMUI Web 框架中的組件應該只收納通用組件,即跨項目組件。優化

精準表達 View

精準表達 View 是指在命名 DOM 節點時要明確這是一個怎樣的 View,這裏的 View 指的就是 UI 層面上這個元素表示的含義,常見的場景是,一個命名爲 resume_head 的元素,在經歷屢次迭代後實際在代碼中卻充當了頁腳,這樣的命名在多人協做時很容易給後面的開發者形成困擾,而精準表達 View 則要求咱們明確一個 UI 元素的含義,並在命名時準確地表達。編碼

基礎樣式配置與半封裝組件

前面的「Class-name 命名規範」主要是在規範層面上去實踐 QMUI Web 的核心理念,而接着更多地就是在代碼層面上去實踐了,主要包括三點:

  • 半封裝組件,即面向項目的組件。
  • 使用組合而不是繼承。
  • 顆粒度的把控。

半封裝組件即面向項目的組件

前文提到,QMUI Web 把組件劃分爲通用組件,項目全局組件,業務組件三種組件,而 QMUI Web 框架收納的則是通用組件,也是跨項目的組件,但每一個項目的 UI 表現並沒有關聯,如何處理跨項目組件就成爲了一個問題。爲此,QMUI 在處理組件時採起的是「半封裝」的處理方式,QMUI 框架封裝的是代碼,所謂半封裝,即封裝那些與項目具體 UI 表現沒有必然聯繫的代碼。例如按鈕組件,QMUI Web 中只封裝了文字居中對齊,鼠標手型,瀏覽器樣式重置,低版本 IE 兼容性處理等代碼,而經常使用的樣式如邊框、背景、字體表現等,都抽取成變量控制,這些組件的變量最終都聚集到一個配置表 Sass 文件中,配合全局的顏色變量、字體變量等變量,就能夠作到跨項目抽取組件,每一個新項目只須要關注具體 UI 表現而無需再處理各類常見的 UI 問題,同時方便地經過調整這些變量的值而快速修改整個項目的樣式。

image_1boupcrpp1okoc05117ar1g1g9h13.png-224.3kB

組合而不是繼承

在處理組件時,繼承的方式是指一個組件類承擔複雜的功能,而組合的方式則是把組件類拆分紅一個基類,以及多個子類,每一個子類承擔的功能不重複,對於咱們的主場景——頻繁迭代,保持穩健,顯然組合會更加適合,這種方式避免了在頻繁的迭代中須要不斷修改組件類,每次迭代只須要修改對應的子類便可。

顆粒度

對於組件的抽取,時常要考慮顆粒度的劃分,顆粒度自己就是一個比較開放性的問題,在這裏與你們分享一些沉澱的經驗:

  • 抽取組件以 UI 表現爲區分,例如一個刪除按鈕,是以刪除 icon + 刪除文案做爲內容的,但在表現上它就是一個帶 icon 的文字按鈕,所以就抽取出一個支持 icon 的文字按鈕,而不用只侷限於按「刪除」這個業務來命名組件。
  • 抽取組件能夠選擇較大的顆粒度,也能夠選擇較小的顆粒度。顆粒度較大的組件實現複雜,能對應複雜的場景,但擴展性也會所以降低,而顆粒度較小的組件則實現簡單,能輕鬆實現一個主場景,但又方便擴展,能靈活地應對變化。所以建議是像按鈕、輸入框、下拉菜單這類一般位於頁面 DOM Tree 末端的元素能夠抽取成儘可能簡單的組件,同時經過擴展的方式去處理各類場景差別。而其餘複雜的組件則能夠專一於一個業務,沒必要過多地考慮不一樣的場景,不然組件很容易變得難以維護。

以上即是 QMUI Web 具體的設計理念,經過命名規範、基礎樣式配置與半封裝組件來保證多人協做時的高效率與可維護性,也使得一個 UI 框架能爲不一樣的項目服務。

具體組成

做爲一個框架,QMUI Web 主要提供了四種能力來提高 UI 開發的效率與質量,對應前文提到的框架設計理念,QMUI Web 提供的這些功能都是爲了幫助開發者方便地控制項目總體樣式,應對頻繁變更,同時保持代碼穩健。

基礎配置與組件

前文提到,框架中會有一份配置表,是各類 Sass 的變量,這些變量控制了一個網頁基本的字體樣式,連接顏色,通用組件的樣式配置等基礎樣式,在建立一個新項目時,應該先根據設計稿配置好這些信息,當這些信息配置完成,那麼一個項目的基本樣式就能夠快速實現了。例以下圖中這些配置屬於 QMUI 通用配置,經過修改這些配置則能夠快速修改項目的字體策略、正文字體大小,連接顏色等 UI 經常使用的 CSS 屬性。

image_1bouqhakqcnr163ruqeubm1n8d1g.png-449.6kB

內置工做流

QMUI 中包含一個基於 gulp 的內置工做流,用於快速解決大量重複勞動力的工做,從而提高效率。QMUI 的 gulp 中預先實現了監控 Sass 文件並自動編譯和優化,雪碧圖處理,模板 include 能力(能夠傳參和使用條件判斷),瀏覽器自動刷新,圖片壓縮,文件清理,文件合併以及自動變動等能力。

image_1bour0k6d13ff1o8k170hed81o8v1t.png-256.4kB

Sass 加強支持

QMUI 中提供了大量基於 Sass 的 CSS 預處理的方法,包括 CSS Reset,一些常見的 CSS 類(例如清除浮動),計算長度值的簡便方法(例如獲取 padding 在某個方向的值,計算兩個長度值的中間值),快速實現一些樣式效果的工具方法(例如實現 border 三角形,適應多倍屏幕的 1px 邊框等),這些都是用於提升樣式開發的效率和質量。

擴展組件

擴展組件並非由 QMUI Web 的主源碼提供,而是由 Demo 提供,一般是由於這類組件結構較複雜,所以業務性沒法很好地剝離,從而不能抽取成公共組件,所以這類組件就放在一個 Demo 頁,以參考組件的形式幫助開發。

GUI

咱們提供了一個用於管理 QMUI Web 項目的桌面 App,在代碼層面它獨立於 QMUI Web 的源碼。它經過 GUI 界面處理 QMUI Web 的服務開啓/關閉,並提供了編譯提醒,出錯提醒,進程關閉提醒等額外的功能,在處理多項目,多分支時能更方便地進行開發。

image_1boura6cn1qm81sqj1hlev127tj2a.png-192.8kB

優化和開源

在經歷較長時間的迭代後,QMUI Web 也逐漸完善起來,此時咱們也開始將 QMUI Web 進行開源。開源意味着 QMUI Web 會進入更加全面的環境中去打磨,在框架的非主體內容如代碼規範、註釋、文檔上面也須要更費心思,考慮的點也須要更加周全。這對團隊來講無疑是個很好的機會,能夠有更多的渠道審視框架,吸取建議,持續進行優化。

在加入開源的大環境後,咱們從 Github、社區論壇中都獲取了很多建議,除了 bug 的反饋外,也指出了一些待完善的地方和提出一些優化的解決方案,從而使得 QMUI Web 注入了更多活力,所以咱們也逐步進行了如「自動化測試用例」、「gulp 結構化」,「引入 SassDoc 自動化生成文檔」,「編譯 Sass 時引入增長更新」等優化,其中很多優化點咱們也在項目的 Github Wiki 中進行了詳細的分享,有興趣的用戶能夠自行瀏覽。

總結與展望

至此,QMUI Web 發展爲如今這套完整的方案,也終於開源到 Github Tencent 與你們分享,咱們指望經過開源與你們進行更多的交流,也使得 QMUI Web 進入更加全面的環境中去打磨,造成對代碼規範、註釋、項目文檔感謝公司與部門給咱們提供了一個平臺,能夠在大型項目中經歷迭代和沉澱。開源只是一個開始,咱們後續仍會不斷進行探索和優化,期待更好的 QMUI Web。

關注 QMUI Web, 來 Github 給咱們 star 吧!

https://github.com/Tencent/QMUI_Web

相關文章
相關標籤/搜索