當前位置:
首頁 > 科技 > 如何設計優秀的 HTML API

如何設計優秀的 HTML API

前言


最近時間能感覺到明顯不夠用了,也就少了早上的2個半小時。今日早讀文章來自 @ 王自健授權並翻譯分享。


正文從這開始~


作為 JavaScript 開發者,我們經常忘記並不是所有人都像我們一樣了解 JavaScript,這被稱為知識的詛咒:當我們精通某個內容的時候,我們就不記得自己作為新人的時候有多麼困惑。我們總是對其他人的能力估計過高,因此我們覺得,自己寫的類庫需要一些 JavaScript 代碼去初始化和配置也很 OK。然而,一些用戶卻在使用過程中大費周折,他們瘋狂地從文檔中複製粘貼例子並隨機組合這些代碼,直到它們生效。


你或許會想,「但是所有寫 HTML 和 CSS 的人都會 JavaScript,對吧?」你錯了。來看看我的調查結果吧,這是我所知道的唯一的相關數據了。(如果你知道任何適用於這個話題的調查,請在評論中說明!)

如何設計優秀的 HTML API



測試:「你對 JavaScript 好感如何?」(2016 年 1 月 22 日)


每兩個寫 HTML 和 CSS 的人中就有一個對 JavaScript 沒有好感。1/2,讓我們感受一下這個比例。


舉個例子,來看以下的代碼,該代碼用來初始化一個 jQuery UI 自動完成庫,摘自其文檔。


Tags:


$(function(){


varavailableTags=[


"ActionScript",


"AppleScript",

"Asp",


"BASIC",


"C"


];


$("#tags").autocomplete({


source:availableTags


});


});


這很簡單,即使對那些根本不會 JavaScript 的人來說也很簡單,對吧?錯。一個非程序員在文檔中看到這個例子的時候,腦子裡會閃過各種問題:「我該把這段代碼放哪兒呢?」「這些花括弧、冒號和方括弧是些什麼鬼?」「我要用這些嗎?」「如果我的元素沒有 ID 怎麼辦?」等等。即使這段極其簡短的代碼也要求人們了解對象字面量、數組、變數、字元串、如何獲取 DOM 元素的引用、事件、 DOM 樹何時構建完畢等等更多知識。這些對於程序員來說微不足道的事情,對不會 JavaScript 的只會寫 HTML 的人來說都是一場攻堅戰。


現在來看一下 HTML5 中的等效聲明性代碼:

Tags:


ActionScript


AppleScript


Asp


BASIC


C


這會讓寫 HTML 的人看得更清楚更明白,在程序員看來更為簡單。我們看到所有的內容都同時被設置好,不必關心什麼時候初始化,如何獲取元素的引用和如何設置每個內容,無需知道哪個函數是用來初始化或者它需要什麼參數。在更高級的使用情況中,還會添加一個 JavaScript API 來允許動態創建屬性和元素。這遵循了一條最基本的 API 設計原則:讓簡單的內容變得更簡單,讓複雜的內容得以實現。


這給我們上了一堂關於 HTML API 的重要課程:HTML API 不光要給那些了解 JavaScript 但水平有限的人帶來福音,還要讓我們 —— 程序員 —— 在普通的工作中也要不惜犧牲程序的靈活性來換取更高的表述性。然而不知怎的,我們在寫自己的類庫的時卻總忘記這些。


那麼什麼是 HTML API 呢?根據維基百科的定義,API(也就是應用程序介面)是「用於構建應用程序軟體的一組子程序定義、協議和工具」。在 HTML API 中,定義和協議就是 HTML ,工具在 HTML 中配置。HTML API 通常由可用於現有 HTML 內容的類和屬性模式組成。通過 Web 組件,甚至可以像玩遊戲一般自定義元素名稱和 Shadow DOM,HTML API 甚至能擁有完整的內部結構,並且對頁面其餘部分隱藏實現細節。但是這並不是一篇關於 Web 組件的文章,Web 組件給予了 HTML API 設計者更多的能力和選擇,但是良好的(HTML)API 設計原則都是可以舉一反三的。


HTML API 加強了設計師和工程師之間的合作,減輕工程師肩上的工作負擔,還能讓設計師創造更具還原度的原型。在類庫中引入 HTML API 不僅讓社區更具包容性,最終還能造福程序員。

並不是每個類庫都需要 HTML API。 HTML API 在使用了 UI 元素的類庫中非常有用,比如 galleries、drag-and-drop、accordions、tabs、carousels 等等。經驗表明,如果一個非程序員不能理解該類庫的功能,它就不需要 HTML API。比如,那些簡化代碼或者幫助管理代碼的庫就不需要 HTML API。那 MVC 框架或者 DOM 助手之類的庫又怎會需要 HTML API 呢?


目前為止,我們只討論了 HTML API 的定義、功能和用處,文章剩下的部分是關於如何設計一個好的 HTML API。


初始化選擇器


在 JavaScript API 中,初始化是被類庫的用戶嚴格控制的:因為他們必須手動調用函數或者創建對象,他們精確地控制著其運行的時間和基礎。在 HTML API 中,我們要幫用戶選擇,同時也要確保不會妨礙那些仍然使用 JavaScript 的用戶,因為他們可能希望得到完全控制。


最常見的兼容兩種使用場景的辦法就是,只有匹配到給定的選擇器(通常是一個特定的類)時才會自動初始化。Awesomplete 就是採用的這種方法,只選取具有 class="awesomplete" 的 input 元素進行初始化。


有時候,簡化自動初始化比做顯式選擇初始化更重要。這很常見,當你的類庫需要運行在眾多元素之上時,避免手動給每個元素單獨添加類比顯式選擇初始化更加重要。比如,Prism 自動高亮任何包含 language-xxx 類的 元素(HTML5 的說明中建議指定代碼段的語言)及其包含 languate-xxx 類的元素內部的 元素。這是因為 Prism 可能會用在一個有著成千上萬代碼段的博客系統中,回過頭去給每一個元素添加類將會是一項非常巨大的工程。


在可以自由地使用 init 選擇器的情況下,允許選擇是否自動化將會是一個良好的實踐。比如,Stretchy 默認自動調整每個 、 和 的尺寸,但是也允許通過 data-stretchy-filter 屬性自定義指定其他元素為 init 選擇器。Prism 支持 元素的 data-manual 屬性來完全取消自動初始化。良好的實踐應該允許 HTML 和 JavaScript 都能設置這個選項,來適應 HTML 和 JavaScript 兩種類庫的用戶。


最小化初始標記


那麼,對於 init 選擇器的每個元素來說,你的類庫都需要其有一個封包、三個內部的 button 和兩個相鄰的 div 該怎麼辦呢?沒問題,自己生成就好了。但是這種磨磨唧唧的工作更適合機器,而不是人。不要期望每個使用類庫的人都同時使用了一些模板系統:許多人還在使用手動添加標記,他們會發現這樣建造系統太過複雜。因此,我們有義務讓他們活的輕鬆一點。


這種做法也最小化了錯誤風險:如果一個用戶僅僅引入了用來初始化的類卻沒有引入所有需要的標記怎麼辦?如果不需要添加額外的標記,就不會產生錯誤。

這條規則中有一個例外:優雅地退化並漸進地增強。比如,即使單個具有「 data- * 」屬性的元素並在「 data-* 」中添加所有選項就可以實現,在嵌入推文的時候也還是會涉及很多標記。這樣做是為了在 JavaScript 載入和運行之前就使得推文可讀。一個良好的經驗法則就是捫心自問,即使在沒有 JavaScript ,多餘的標記能否給終端用戶帶來好處?如果是,那麼就引入;如果不是,那就要用類庫生成。


便於用戶使用還是讓用戶自定義也是一組經典的矛盾:自動生成所有的標記會易於用戶使用,讓用戶自定義又顯得更加靈活。在你需要的時候,靈活性如雪中送炭,在不需要的時候卻適得其反,因為你不得不手動設置所有的參數。為了平衡這兩種需要,你可以生成那些需要但不存在的標記。比如,假設你需要給所有的 .foo 元素外層添加一個 .foo-container 元素。首先,通過 element.closest(".foo-container") 檢查 .foo 元素的父元素或者任何的祖先元素(這樣最好了)是否含有 foo-container 類,如果有的話,你就不用生成新的元素,直接使用就可以了。


設置


典型地,設置應該通過在恰當的元素上使用 data-* 屬性來實現。如果你的類庫中添加了成千上萬的屬性,然後你希望給它們添加命名空間來避免和其他類庫混淆,比如這樣 data-foo-*(foo 是基於類庫名字的一到三個字母長度的前綴)。如果名字顯得太長,你可以使用 foo-*,但是要有心理準備,這種方式會打破 HTML 驗證並且會使得一些勤勞的 HTML 作者因此而棄用你的類庫(因為他們寧願費點力氣,也不願意使用這種命名。譯者注。)。理想情況下,只要代碼不會太臃腫,以上兩種情況都應該支持。目前還沒有完美的解決辦法,因此在 WHATWG 中展開了一場如火如荼的討論:是否應該讓自定義的屬性前綴合法化。


儘可能地遵從 HTML 的慣例。比如,你使用了一個屬性來做布爾類型的設置,當該屬性出現時無論其值如何都被視為 true,若不出現則被視為 false,不要期望可以用 data-foo="true" 或者 data-foo="false" 來代替。當然 ARIA 是這樣做的,但是如果 ARIA 哪天突然死翹翹了,你也想那樣嗎?


你也可以使用類進行布爾值設置。典型地,類的語法和布爾屬性值類似:類存在的時候是 true 不出現的時候就是 false。如果你想反過來設置,那就用一個 no- 前綴(比如,no-line-number)。但是要記住,類名可不像屬性一樣只有 data-*,因此這種方式很可能會和用戶現存的類名衝突,因此你可以考慮一下在類名中使用 foo- 這樣的前綴來避免衝突。但也有可能在後期的維護中發現這些類並未被 CSS 使用所以誤刪,這又是另一個隱患。


當你需要設置一組相關的布爾值時,使用空格區分會比使用多個分隔符的方式好很多。比如,


就比


好得多,因為後者可能會造成很多的衝突。你還可以使用 ~= 屬性選擇器來定位單個元素,比如 element.matches("[data-permissions~=read]") 可以檢查該元素是否有 read 許可權。


如果設置內容的類型是數組或者對象,那麼你就可以使用 data-* 屬性來關聯到另一個元素。比如, HTML5 中的自動完成:因為自動完成需要一個建議列表,你可以使用 data-* 屬性並通過 ID 聯繫到包含建議內容的 元素。

HTML 有一個慣例很讓人頭痛:在 HTML 中,用屬性聯繫到另一個元素通常是靠引用其 ID 實現的(試想一下 )。然而,這種方法相當受限制:如果能夠允許使用選擇器或者甚至允許嵌套將更為方便,其效果將會極大地依賴於你的使用情況。要記住,穩定性重要,但實用性更加重要。


即使有些設置內容不能在 HTML 中指定也沒關係。在 JavaScript 中以函數為設置值的部分被稱作「高級自定義」。試想一下 Awesomplete:所有數字、布爾值、字元串和對象都可以通過 data-* 屬性(list、minChars、maxItems、autoFirst)設置,所有的函數設置只能通過 JavaScript 使用(filter、sort、item、replace、data),這樣會寫 JavaScript 函數來配置類庫的人就可以使用 JavaScript API 了。


正則表達式(regex)處在灰色地帶:典型的,只有程序員才知道正則表達式(甚至程序員在使用的時候也會有問題!);那麼,乍看之下,在 HTML API 中引入正則表達式類型的設置並沒有意義。然而,HTML5 確實引入了這樣的設置(),並且我相信那很成功,因為非程序員能在正則詞典中找到他們的用例並複製粘貼。


繼承


如果你的 UI 庫在每個頁面只會調用一兩次,繼承將不會很重要。然而,如果要應用於多個元素,通過類或者屬性給每個元素做相同的配置將會非常令人頭痛。記住並不是每個人都用了構建系統,尤其是非程序員。在這些情況下,定義能夠從祖先元素繼承設置將會變得非常有用,那樣多個實例就可以被批量設置了。


還拿 Smashing Magazine 中使用的時下流行的語法高亮類庫 —— Prism 來舉例。高亮語句是通過 language-xxx 形式的類來配置的。是的,這違反了我們在前文中談過的規則,但這只是一種主觀決策,因為 HTML5 手冊中建議如此。在有許多代碼段的頁面上(想像一下,在博客文章中使用內聯 元素的頻率!),在每個 元素中指定代碼語句將會非常煩人。為了緩解這種痛苦,Prism 支持繼承這些類:如果一個 元素自己沒有 language-xxx 類,那麼將會使用其最近的祖先元素的 language-xxx 類。這使得用戶可以設置全局的代碼語句(通過在 或者 元素上設置類)或者設置區塊的代碼語句,並且可以在擁有不同語句的元素或者區塊上重寫設置。


現在 CSS 變數已經被所有的瀏覽器支持,它們可以用於以下設置:他們默認可以被繼承,並且可以以內聯的方式通過 style 屬性設置,也可以通過 CSS 或者 JavaScript 設置。在代碼中,你可以通過 getComputedStyle(element).getPropertyValue("--variablename") 獲取它們。除了瀏覽器支持,其主要的劣勢就是開發者們還沒習慣使用它們,但是那已經發生改變了。並且,你不能像監視元素和屬性的一般通過 MutationObserver 來監視其改變。


全局設置


大多數 UI 類庫都有兩組設置:定義每個組件表現形式的設置和定義整個類庫表現形式的全局設置。目前為止,我們主要討論了前者,你現在可能在好奇全局設置該在設置在哪裡。


進行全局設置的一個好地方就引入類庫的 元素。你可以通過 document.currentScript 獲取該元素,這有著非常好的瀏覽器支持。好處就是,這對於設置的作用域非常清楚,因此它們的名字可以起的更短(比如 data-filter 而不是 data-stretchy-filter)。

然而,你不能只在 元素中進行設置,因為一些用戶可能會在 CMS 中使用你的類庫,而 CMS 中不允許用戶自定義 元素。你也可以在 和 元素或者甚至任何地方設置,只要你清楚地聲明了屬性值重複的時候哪個會生效。(第一個?最後一個?還是其他的?)


文檔


那麼,你已經掌握了如何在類庫中設置一個漂亮的聲明性的 API。棒極了!然而,如果你所有的文檔都寫得只有會 JavaScript 的用戶才看得懂,那麼就只有很少人能使用了。我記得曾經看過一個很酷的類庫,基於 URL 並通過切換元素的 HTML 屬性來切換元素的表現形式。然而,這漂亮的 HTML API 並不能被其目標人群所使用,因為整篇文檔中都充滿了 JavaScript 引用。最開始的例子是這樣開始的「這和 location.href.match(/foo/) 等價。」非程序員哪能看懂這個呢?


同時要記得許多人並不會任何編程語言,不光是 JavaScript。你期望用戶能夠讀懂並理解的文中的模型、視圖、控制器或者其他軟體工程觀念,結果無非是讓他們摸不著頭腦並且放棄。


當然,你應該在文檔中寫 API 里 JavaScript 的內容,你可以寫在「高級使用」部分。然而,如果你在文檔一開頭就引用 JavaScript 對象和函數或者軟體工程的觀念,那麼你實質上就是在告訴非程序員這個類庫不是給他們用的,因此你就排除了一大批潛在用戶。不幸的是,大部分的 HTML API 類庫文檔都受這些問題困擾著,因為 HTML API 經常被視為是程序員的捷徑,而並不是給非程序員使用的。慶幸的是,這種狀況在未來可以有改變。


那麼 Web 組件呢?


在不遠的未來,Web 組件百分之百將會徹底改變 HTML API。 元素將會允許作者提供惰性載入的腳本。自定義元素將使得用戶可以像原生的 HTML 一樣使用更多優雅的 init 標記。引入 HTML 也將使得作者能夠僅引入一個文件來替代三個樣式表、五個腳本和十個模板(如果瀏覽器能夠同時獲取並且不再認為 ES6 模塊是一種競爭技術)。Shadow DOM 使得類庫可以將複雜的 DOM 結構適當壓縮並且不會影響用戶自己的標記。


然而除了 ,瀏覽器對其他三個特徵的支持目前受限。因此他們需要更高的聚合度,以此來減少對類庫的影響。然而,這將會是你在未來一段時間裡需要不斷關注的東西。


MarkApp:一個 HTML API 類庫的列表


如果你已經聽取了這篇文章中的建議,那麼恭喜你已經能夠把網站做得更好,更有包容性和更有創造性了!我在 MarkApp 上維護著一些使用 HTML API 類庫的列表。請發 Pull Request 給我來添加你自己的內容!

如何設計優秀的 HTML API



關於本文


譯者:@ 王子建


校對者:@ 薛定諤的貓、@zhangqippp


譯文:https://github.com/xitu/gold-miner/blob/master/TODO/designing-html-apis.md(掘金翻譯計劃)


原文:HTML APIs: What They Are And How To Design A Good One


作者:Lea Verou


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 前端早讀課 的精彩文章:

廣州唯品會,找像你這樣優秀的工程師
騰訊Web前端大會熱力來襲
比較與理解React的Components,Elements和Instances
高效前端團隊的秘密
程序員拿什麼來學英語

TAG:前端早讀課 |

您可能感興趣

IBM、Intel、NVIDIA和 AMD 等因 AI 工作負載「將重新設計處理器」
中國設計驚艷巴黎,PLAY LOUNGE HARMONY時裝藝術展
DIESEL 正式啟動THE RED TAG 設計計劃
ANDREW MARTIN DAY 設計盛典,圓滿落幕!
CUUNION CONCEPT FAIR 設計聯合概念展:尋找「中國版「設計
三星重新設計ISOCELL Dual雙攝方案:中、低端機皆可用
當代藝術感 ALVORADA別墅設計
Jessica個人品牌BLANC&ECLARE的設計你喜歡?
平面設計:WUWENQIAONI
了解SOLIDWORKS 2018如何構建優秀的設計
SONY XPERIA XZ2 發布!全新設計ID,更強悍的慢動作拍攝
CdG PLAY的愛心設計師,這次聯合NBA球衣大改造!
AGLOIDVSE首席設計師GODS.L先生精心設計「財相」祝大家新年好運
MVRDV:城市先行者 INTERNI設計時代專訪
菲董也要發力!BILLIONAIRE BOYS CLUB x adidas Originals 良心設計細節曝光!
產品設計師 REID SCHLEGEL 的草稿圖繪本
Mi MIX 2s最新設計圖:可以媲美Vivo APEX概念機的小米手機
TFBOYS王俊凱設計的NIKE Air Max Zero發售信息確認!這次會搶嗎?
MVRDV:城市先行者 | INTERNI設計時代專訪
「IKEA」還是「NITORI」?室內設計如何將二者合而為一