面向設計的半封裝web元件開發

發表於2016-01-27

前言

本文內容可謂是對大腦認知的一場洗禮。我們平常提到元件,就會想到重用,各個專案都能使用。而本文的元件,對於某具體專案而言是元件,但是,對於其他專案,就是個半封裝的半吊子元件。面向設計、面向專案的web元件開發,就是本文要探討的主旨。

一、人與元件

目前這個階段,我們所使用的web元件都是人所編寫的,因此,人這個個體在賦予元件生命的時候就扮演了至關重要的角色。人的技能背景,個人喜好,甚至世界觀都可以從元件中得到體現。但人無完人,因此要想誕生一款完美的元件,需要上下游很多優秀的同事,把自己最棒的世界融入進去,協作完成,其中下面這4個職位參與度較高:

面向設計的半封裝web元件開發

注意到了沒有,前端開發人員處於web元件開發流程的下游;這其實沒什麼,大家通力協作,元件弄好,專案做好,產品做好,皆大歡喜。然而實際上,由於大學沒有前端專業,因此負責團隊web元件開發的,大多是從與元件幾乎不相干的後臺開發轉過來的,或帶有明顯的後臺開發烙印的。也就是說,前端開發不僅處於下游,還有1/3的身子在web元件之外。

面向設計的半封裝web元件開發

一個web元件的誕生,理想狀態應該是需要設計、UI工程師、前端開發通力協作完成的。有句話怎麼說來著,理想很豐滿,現實很骨感。

現實是:大多數web元件都是前端開發人員一個或數人,按照業界約定俗成的套路實現的,超前於UI設計,遊離於UI重構。什麼意思呢?比方說一個彈出層元件,有標題、關閉按鈕、主內容區域,底部確定/關閉按鈕。這套結構是業界約定俗成的,開發人員在寫這些元件的時候,會發揮自己的聰明才智,好好地封裝,好好地設計API, 目的就是可以不用關心以後設計師設計的彈出層長什麼樣子,因為我預留了類名介面,UI工程師換個皮膚就好了;同時能保證元件的整站複用。也就是專案開始之前,成熟、封裝良好、API豐富的web元件就已存在。

親們,讀到現在,你們是不是覺得沒什麼問題,挺好的啊!?對的,在iPhone出現之前,大家都覺得Nokia挺好的。

從人的角度講,這種看似牛逼的路數最大的問題就是無視了分工,所謂術業有專攻,聞道有先後,開發再逆天,也是存在侷限的,或者說是人性上很難避免的東西。

1. 位置與角色

大家應該都知道,設計師和程式設計師處於兩個不同世界的,因此,當其中一個角色獨自承擔另外一個角色工作的時候,自然會存在諸多阻礙,其中很重要的一點就是設計重心。

前端開發寫web元件,實際上也是一種程式碼的設計,此時,這些程式設計師氣質濃郁的前端開發人員設計的重點自然是放在元件功能、通用性、擴充套件性以及易用性上,畢竟這一塊是自己擅長的,至於UI,會預留API或其他介面,也能滿足常規的設計需求。

如果互動設計師或UI設計師來寫web元件, UI和互動可定製則是其設計的重心,發展得好的話,可以直接成為另外一種流派,直接和(開發背景前端的)面向功能的web元件流派相抗衡。但是,國內的現狀是,設計師一般不參與直接的程式碼建設。

實際上,從職位上劃分,UI開發應該是最適應構建web元件的角色,能兼顧設計之美,重構之美,以及程式碼之美。只可惜由於門檻低,水平良莠不齊,尤其JS方面的駕馭能力有限,於是,最後的結果是,元件的建設都落在了工程氣息濃重的開發身上。

可以看到,雖然不合理,但是情非得已。有人可能要叫了:“囉哩吧嗦,狗皮膏藥塗到現在,到底哪裡不合理,你到是說啊!”

OK, 稍安勿躁。由於元件這東西只能開發實現,導致在元件的設計以及使用上,前端開發有了非常大的話語權,下游決定了上游,設計師以及CSSer在元件眼中就是個擺設。比方說設計師對dialog彈框進行了某些微創新,比方說下面這樣的(無標題無關閉大背景色塊):

面向設計的半封裝web元件開發

去問開發可行性,結果,開發來了一句:“哎呀,這個功能我們的彈框元件目前不支援!”我相信這種場景很多同學都遇到過吧~最後,基本上都是設計師妥協,面向設計的半封裝web元件開發使用傳統彈框互動或佈局。所以,坊間才有“苦逼的設計師”的傳聞。

苦逼的設計師這樣苦逼地工作了很多年,還好,大家就這麼過來了。然而,事物是不斷髮展的,技術是不斷進步的,隨著CSS3, SVG等現代web技術日趨成熟,我們在UI展現層能夠做的事件就非常多,更新變化也更加快。在這種大環境背景下,還讓開發來決定設計,顯然這對產品是不負責任的。其他競品在元件UI細節上不斷閃現人性化、情感化的創新之處,互動也更加流暢與舒適;而你還抱著“我們這是成熟的彈框元件,不能隨便改”的想法固步自封,使用”duang duang duang”生硬,機械,呆板的彈框元件,註定在現代web浪潮中被衝到沙灘上。

對於頁面工程師,切圖仔而言,其實也挺苦逼的。在部門沒啥地位的頁面仔們,苦學了一種新的佈局,比傳統實現少巢狀2層標籤,且滿足各種場景需求,好棒!面向設計的半封裝web元件開發 結果交接的開發來了句“我們的選項卡元件不支援你這種結構,你需要調整下”。

具體專案的具體元件本來就應該是大家通力協作完成的,現在就因“元件是我寫的,我就是發言人”的心態限制設計、重構的創造力。這就是不合理之處。

2. 揚長避短

元件的作用是什麼呢?就是“偷懶”,來個新頁面,“啪”一套;來個新專案,也是“啪”一套。功能棒棒噠,任務完成,老婆再也不用擔心我加班晚歸啦!

偷什麼懶呢?主要是偷自己不擅長那塊的懶。這是人之常情。設計師不懂程式碼,他希望的元件是,直接視覺化操作就OK的;頁面製作人員,他希望的元件是JS功能那塊它不需要操心;前端開發們,則希望元件HTML佈局那塊不需要關心。

好了,現在元件都是開發背景的前端寫的,所以呢,很多HTML佈局啊,樣式表現啊,都整合在了web元件中,一些動態的表現就使用洋洋灑灑的API控制。於是,開發使用的時候,只要按照特定的套路,自己不需要去寫頁面之類的,元件就棒棒噠了!

這樣的例子很多的,比方說知名開源專案kissy中的選項卡元件,根據我的觀察,其選項卡要麼是要通過JS指令碼動態建立,任何特異化的需求都是通過豐富的API介面或者回撥實現的。總之,元件的使用只需要玩弄JS, 不需要把玩HTML; 要麼就是套用固定的HTML結構以及className值。這比較符合JS造詣很深的前端開發的偷懶模式。

等等,篇幅原因,就不一一舉例。

這並沒有什麼對錯之分。有的企業就是功能為王,業務導向;有的企業就是產品為王,體驗優先。不同的企業文化,不同的產品要求,不同的團隊規模與技術能力,決定了web元件的表現形態、使用方式等。只要符合企業的生產與成長需要,都是很棒的web元件。因此,類似kissy這樣的模組集合,是否適用於單兵作戰的中小企業以及注重使用者體驗的創業團隊,就需要執行者好好斟酌斟酌了!說不定,jQuery UI可能更合適一點。

至少對於我而言,絕不會去使用對HTML做過多限制的web元件的(例如要求節點必須如何如何…):

KISSY 1.4 srcNode 初始化元件時必須要求內容節點必須包含類名 ks-overlay-content (這裡 ks- 為 prefixCls)…

“揚長避短”原本是個褒義詞,顯然,我放在這裡講,是要說其不好的。有句話講的好,叫做術業有專攻。前端開發都會HTML/CSS, 畢竟相比程式開發,門檻很低,在相關領域也浸染了些年月,構建web元件的時候,感覺HTML/CSS方面的應用也是比較順手的,功能也都能跑起來。但是,在HTML/CSS方面造詣很深的開發看來,前端開發web元件的HTML結構等設計不敢恭維。舉個真實的例子:

要實現一個相對文字框定位的Autocomplete元件(相比絕對定位, resize時候無需JS重定位),前端開發是這麼實現的,在<input>文字框外面wrap包裹了一層<div>標籤,設定positionrelative, 然後Autocomplete主列表容器就在這個包裹<div>裡面,絕對定位於該<div>, left/top值與文字框尺寸關聯。

面向設計的半封裝web元件開發

最後的實現,效果是有的,相容性也是可以的,在前端開發看來應該是OK的,自我滿意的。但是,在我看來是相當糟糕的!

這外面包裹的一層<div>標籤完全是多餘的,我們無需包括標籤就能實現我們想要的相對文字框定位效果,而且相容IE6+. 目前的實現,這個包裹的<div>看上去貌似起到了輔助劑的作用,實際上留下了超級隱患,讓元件生命力(適用性)立馬降低50%。

小隱患是,可能相鄰父子選擇器會失效,比方說.parent > input選擇器,會因為莫名其妙爸爸變爺爺導致文字框樣式失效,這個問題嘛,改改CSS就可以了;以及多了一個relative, 元素的z-index層級管理又更復雜了一步,維護成本增加了!

超級大隱患是,Autocomplete元件下拉框高度超出容器高度是很常見的,但是,由於你外層有了一個position:relative的父級,只要外面任意一個容器有overflow:hidden,你的Autocomplete下拉就會被攔腰斬斷,部分內容不可見;如果是overflow:auto/scroll,則會出現討厭的滾動條。這個元件基本上就廢了!但是,如果沒有外面這層討厭的position:relative父級,overflow:hidden就幹不掉下拉選單,Autocomplete元件就能長青不老,適用性提升了整整一個量級。

上面截圖,仔細看會發現有個*-placeholder<label>元素,先不說這個label元素沒有for屬性,要知道,企業產品近8成使用者的瀏覽器都支援原生placeholder(包括顏色等自定義),對於這部分瀏覽器,我實在想不出任何需要自定義實現placeholder效果的理由。最大的可能性是前端開發童鞋不知道目前凡是支援placeholder屬性的瀏覽器都可以CSS自定義吧。也就是前端開發本身的技術深度以及視野的侷限。

我們對上面的絮叨總結下,就是想表達,人的侷限性帶來了web元件的侷限性,唯有相互協作,告別單職挑大樑,才能讓web元件有所突破。但是,目前這個階段,這現實嗎?優秀的前端如此匱乏,尤其能夠上下游承接的,想尋求突破,我們是不是可以從別的地方入手?

二、元件的抽象與封裝

我們在寫web元件的時候,我們總是會盡可能地去抽象功能,封裝API。 於是,當我們使用這些元件的時候,我們只需要針對一些常用API去做設定,就能滿足我們日常的功能。

在很長一段時間裡,我一直都是這麼做的,業界幾乎所有開源的web元件,包括團隊內的web元件都是這樣的設計思路。

然而,隨著時間推移,在各種型別的專案中浸泡,我發現,儘可能地去通過JS的手段封裝元件似乎不是未來的趨勢,反而可能會成為一種制約。

1. 現代web技術發展

CSS3/HTML5等現代web技術不斷髮展,以及IE6瀏覽器的淘汰。瀏覽器自身能夠完成的事情要比以前多很多很多。舉個極端的例子(都是廠內現有的真實案例),模擬單核取方塊的web元件,如果按照傳統的元件開發模式,API這塊(events回撥API預設)可能就會是下面這樣子:

面向設計的半封裝web元件開發

從程式碼的角度講,還是很美的,對吧;功能上也是可以的,各類需求也能滿足;API的抽象與封裝也是沒有不足。只是,恕我愚鈍,這洋洋灑灑600+行的JS程式碼的價值在哪裡?在IE9+瀏覽器下,單核取方塊的自定義效果是不需要一丁點一絲絲JS程式碼的,對於IE7-IE8瀏覽器,我們只需要關心input本身,全域性委託click, 讓單核取方塊input的類名和checked狀態保持一致就可以了,其他的交給CSS選擇器完成就好了。全部的程式碼量跟上面截圖API引數程式碼量基本上一樣,而且對設計師和頁面重構人員更加友好。

工程化的思維方式,高度的邏輯思維與抽象能力,以及造物者的美妙感覺,似乎讓開發熱衷於設計與封裝API, 熟不知,當新技術出現,或者發現有其他更簡單的實現的時候。那些所謂的封裝是顯得那麼的笨重與雞肋。

“好了,你別說了,我改還不行嗎?”元件這東西,由小變大很簡單,可以向前相容;你想從大變小,我只能呵呵。還是等下一個全新的版本,或者其他完全不相干的專案了,兄弟!

2. 變幻莫測的UI層

現代web技術的發展,讓我們在UI表現上可以有更多的選擇。這對web元件UI這塊的抽象與封裝帶來了很大的挑戰,來看看一些同行的言論吧:

面向設計的半封裝web元件開發

如果有元件自信對UI層進行了完美地抽象與封裝,這表明,這個元件已經對UI層的表現有了很大的限制。這是毋庸置疑的,有些事物本身就是對立的矛盾體,工程化就是要講求一致性,但是,個性化顯然就是需要不一致,而UI表現就是一件很個性化的事情。So, …

當前的web元件面對新專案新的UI表現需求,採用的做法要麼就是new一個新的封裝進行二次封裝,要麼多些寫程式碼做冗餘處理。恩,都不是什麼好做法,不過又沒有辦法。

3. 跨部門的合作

最新,我們完成了一個專案。這個專案質量非常高,無論是UI, 互動和體驗,各方的評價也很好。後來我們要開始一個新的且比較大的專案,就希望把已有專案很多好的東西借鑑過來。設計還是同樣的一批設計師,但是,前端團隊卻換了一撥人。理想的狀態應該是這樣的,新專案的前端團隊,直接使用之前專案這邊的前端UI元件(除了顏色,尺寸什麼的都是一模一樣的),less的變數檔案顏色一改,分分鐘無縫轉移,多棒啊!面向設計的半封裝web元件開發

但是,最後的結果是,新的前端團隊放棄了之前專案的前端解決方案,還是使用了自己的簡潔派做法,seajs + jQuery + …

各位觀眾可能會疑問了,咦,為啥不使用現成的東西啊?主要原因就是上手成本和學習成本,企業這邊的前端元件體系可以和kissy一拼了,物件導向、模組化、按需載入,API封裝也是盡善盡美,走Grunt.js玩nodejs, 前後端分離,走得還挺超前的。但是,自己團隊內部新人有人帶,有人教,可以慢慢上手。但是,你這一套東西交給其他團隊,考慮到其量級以及複雜度,以及專案的緊急程度;一看到你那洋洋灑灑N多的API引數,著實讓人望而生畏。以及還有不可忽略的程式碼風格、模式等差異。

為什麼會有那麼多API?

這個問題很有意思:“為什麼會有那麼多API?” 這個問題可謂是問到點子上了。原本元件誕生的時候,API是沒有這麼多的,後來,現有的API不能滿足某些UI層或互動層的使用場景,於是,前端開發就抽象一下,新增一個API, 滿足這個需求。但是呢,這專案啊是一個接一個,需求呢,也是千變萬化。沒過多久,又來了個需求,開發據理力爭,還是沒能擋掉,結果,又在元件裡新增一個API。 久而久之,就有了現在看到了很多API引數,此時,這個web元件就可以稱為“成熟的web元件”,對外宣傳“適合多種應用場景”。這其實很有意思,所謂的適應性居然是通過增加各種API,增加元件程式碼量實現的,然後還自我得意一番。我開始有些明白為啥小小的單選框模擬元件居然需要600多行的JS程式碼了。

歸根結底,還是“儘可能對元件API進行抽象和封裝”這樣元件編寫意識導致的,這種想法和意識實際上已經不符合發展的趨勢了。

我們看來有必要轉換思維。

三、轉換思維,分離與半封裝

大家都知道YUI已經停止維護有段時間,至於原因,不知道大家有沒有好好體味下(參見下圖言論):

面向設計的半封裝web元件開發

正如我所言,為了滿足UI需求,講求封裝的設計理念,必然會導致web元件越來越大,越來越臃腫;同時,前端開發這個角色由於關注點和職位跨度原因,對於UI層的處理能力和其對JS語言本身的處理能力還是有不小差距的。

因此,考慮到未來發展,我們必須做出適當的改變。我個人覺得可以從這兩方面尋求改變:分離半封裝

1. 分離

實際上,目前的UI元件也是有分離的,很多樣式都可以通過類名控制。然而,這些分離都是逼不得已的,比方說Autocomplete的列表樣式,你總不可能每個列表都內聯一段樣式相同的style設定吧。但是,如果條件允許,樣式控制都是儘可能在JS中完成的,例如Autocomplete的列表容器的尺寸、定位、層級等等;甚至有些元件直接內嵌完整的CSS程式碼。

這樣的設計是奔著足夠封裝,呼叫方便去的。但是對UI的友好程度,恐怕就不是設計者的關注點了。

顯然,這裡要講的“分離”要比傳統的“不得已分離”要更進一步。包括兩方面:

①. 樣式控制從JS分離

即只要是靜態樣式控制,全部交給外部的CSS來完成。甚至包括元件的狀態控制(尤其是隻要支援IE9+的專案),例如顯示,隱藏等等。

拿經典的彈框元件舉例。至於absolute定位,還是fixed定位,背景色是黑色還是其他,透明度多少,彈框是否居中定位等等,元件都不管(目前這類全都JS API控制),元件要關注的是功能層面的東西。千萬不要自己為是,使用JS計算讓彈框居中顯示(外帶resize重計算)。UI需求不是你可控的,比方說我們這邊幾個專案的彈框的需求是上下2:3滾動跟隨顯示,CSS完全可以實現此效果,CSS才是最好的UI樣式API。

說到這裡,忍不住爆料下,由於各種錯綜複雜的原因,專案的彈框元件Overlay的透明度和顏色API目前是個醬油,自定義沒效果。於是,最後還是使用CSS的!important重置了JS的style控制面向設計的半封裝web元件開發。如果當初全都交給CSS, 什麼事都沒有,還省了一大波JS程式碼,呵呵呵!

面向設計的半封裝web元件開發

②. 引數來源從JS分離

舉個最簡單的例子,文字框/文字域的placeholder佔位符效果元件,其佔位符內容通過JS的{ placeholder: '' }引數賦值嗎?很顯然,要優先使用HTML元素上對應的屬性值。這其實是很基本的常識,然而,很多元件只有JS API這一個入口。

或者tips元件的提示內容源自元素的title屬性等。

即符合語義,頁面工程師還可控。一舉多得。

以上的分離,省JS程式碼是小,更大的意義在於釋放了UI設計師以及UI工程師的潛力,使上下游所有的成員角色都參與到web元件的建設中來,只要這個設計師的設計能力>開發,頁面重構人員的重構能力>開發,這個元件的品質,絕對就會比前端開發一個人完成的質量要高。而且,對於其他不同UI風格的專案具有更強的適應性。

2. 半封裝

一提到web元件,我們很自然跟封裝聯絡在一起。對啊,你不封裝怎麼叫做元件呢?現在,我們有必要轉換思維了,要想滿足日益高漲的UI層需求,同時元件不會日趨臃腫,我們就需要對元件進行半封裝。

那問題來了,什麼是“半封裝”呢?

所謂“半封裝”是指我們只封裝語言層面以及功能層面的東西;對於UI層,雖然也是JS, 但我們按照CSS的思維處理,以滿足當前專案UI需求為主,不講求封裝以及API設計,保持隨時的啟用態,無論是UI工程師或者前端開發都可以根據具體專案具體需求調整之。

需要注意的是,此“半封裝”是針對不同設計風格的專案而言,對於某一個具體專案,其web元件還是完全封裝的,還是有成熟的API介面的,小白開發也是可以直接使用的,只是不能直接應用到其他專案!

分離,和半封裝使用示意圖表示就是:

面向設計的半封裝web元件開發

對應的職位參與如下:

面向設計的半封裝web元件開發

從上圖可以看出,我在第一章節大肆分析的當前web元件分工不合理性(見下圖gif)得到了很好地解決。web元件樣式控制CSS化,以及非封裝的HTML結構、類名等大大提高了偏設計的前端對元件建設的參與度,對元件設計品質的提升,非常有幫助。

面向設計的半封裝web元件開發

關於web元件的半封裝性

對於開發思想濃郁的程式設計師,可能有些無法接受這所謂的“半封裝”思想。我cow, 每來一個專案,都要對元件進行一番修整,人力成本怎麼算?如果支援10個專案,就有10個子元件,日後維護怎麼辦?

關於人力成本:
傳統的web元件是由前端開發在原元件基礎上二次封裝成專案需要的web元件,這個成本,跟直接動元件程式碼中的小部分UI層內容,實際上沒什麼區別的,這個下一章節再次提到;

關於維護成本:
首先對於每一個具體專案而言,元件都是通用的,而半封裝,只是對其他專案而言是半封裝,對於具體專案依然是個全封裝的web元件,跟傳統web元件維護成本是一模一樣的;

其次,半封裝的web元件,非封裝的部分是多變的UI層,整體結構依然是物件導向開發,其他部分依然使模組化載入,因此,看上去10個子元件,實際上僅僅是10個跟實際專案緊密契合的UI佈局相關的子元件。要知道,UI層本來就應該具有特異性,獨立開來反而降低了樣式調整帶來衝突的可能性。

最後,對於不同專案而言,元件本身就應該是獨立不耦合、相互無關聯的。比方說jQuery, 10個專案都使用jQuery, 有個專案需要使用jQuery某新特性,於是升級都愛了2.0, 其他專案也要更著升級嗎?顯然是不推薦的,對吧,新版本的瀏覽器相容性可能不一樣,一些老的API可能刪除了。jQuery況且如此,我們實際開發時候,10個專案實際上就是10個元件體系,別看貌似程式碼都是一樣的,維護起來還是要獨立維護。

因此,綜上所述,根本就不存在增加日後的維護成本。

半封裝web元件唯一的問題在於,對小白從業人員不友好。很多新人就是大自然的程式碼搬運工,就是希望元件足夠傻瓜化,最好直接引入一個JS檔案,自己想要的功能就出現了。這就是為何我們平時在網際網路上看到的開源的web元件都是封裝很良好的原因,你使用麻煩,哪個小白會使用!同時,因為需要考慮各種應用場景,API很多,元件很重,為了宣傳,只能美名曰強大、適用於各種場景。正如無招勝有招,沒有使用場景才是最能適用於各種場景。

我們在企業打工吃飯,首先考慮的應該是元件本身的質量、產品和專案的質量,至於開源什麼的,是不是想太遠了。

我們有專業且可愛的同事們,為何要把合作的同事當小白,而不是不發揮各自的特長,一起把產品弄得棒棒噠!?

舉例補刀

就在我寫到這個位置的時候,高階視覺設計師J向我諮詢日期時間選擇元件的時候,出現了這麼一句話:

面向設計的半封裝web元件開發

網上能夠找到的日期時間選擇web元件都是封裝良好的web元件,對於對設計沒要求的小白使用者或者一些小廠很友好,但是,對於對設計很重視的使用場景,所謂的“完全封裝”反而成為了一種制約,且不說元件的class類名風格是否符合團隊規範。

其實,我們希望模組化或者元件化的東西是日期篩選或者排列的演算法。對於UI層,你大肆整合,一了百了。最後的結果呢?被設計師嫌棄了!其實呢,裡面的HTML構建也被HTML工程師嫌棄了!後來,設計師委曲求全接受了一款時間選擇器元件,結果還不支援IE7瀏覽器,真是造化弄人啊!

正在閱讀的你,遇到這種情況你會怎麼辦?試想下,如果我們有一個半封裝的web元件,UI層內容和模組層內容清晰且獨立,此時,UI工程師就可以專心搗鼓UI層內容,可以滿足設計師任何挑剔的需求,豈不美哉?!

四、面向設計高階定製的產品元件

怎樣的產品才高階,有檔次,脫穎而出?

我們可以拿衣服為樣板,回答上面這個問題。

很顯然,私人定製的衣服要比流水線上生產的衣服,要更有檔次,產品品質要更高。

完全封裝的web元件,就好比流水線上的衣服,講求工業化,效率以及成本。但是,這樣的web元件做出來的產品的檔次和質量,未免有粗糙之感。而本文所反覆推崇的半封裝的web元件,非常重視量體裁衣的設計、量身定製的互動,使得我們的web站點猶如私人訂製的高階禮服。在芸芸產品中脫穎而出,贏得口碑。

需要明白的是,私人訂製並意味著完全放棄工業化、模板化的東西。就算你讓玉蘭為你設計高檔禮服,禮服的製作過程中,還是會用到線稿、樣板等等。只是並非完全的流水化。面向設計的半封裝的web元件也是這麼回事,我們還是需要物件導向、需要模組化載入、通用的事件處理等等,只是這些成為了背後的一部分而不是全部。

下面我們一起來看一個很有意思的問題,初期開發成本問題。

面對設計的要求,我們以前的做法是這樣的,web元件不動,針對具體專案,common.js中來個二次封裝;而現在的做法是採用私人定製的方法,在原web元件根據設計需求,搗鼓UI相關內容。差異見下示意圖:

面向設計的半封裝web元件開發

都是需要為了滿足UI的需求做一些工作的,所以前期工作成本並不好評估。但是,可以肯定的是,JS的程式碼量下降了很多,且對於設計對於UI的定製性更強了,如果團隊有很多厲害的設計師,這個web元件的品質就牛大了。

個性化設計與工業化生產的矛盾

每個企業應該都有自己重視的產品,而且都希望這個產品各方面品質都高人一等,對,是各方面品質,這樣才有競爭力,我們騰訊更是看重產品品質。

我們有很多頂尖的產品經理和互動/視覺設計師,設計的web控制元件既美觀又大氣、而且還親近使用者,細節上很多微創新,高品質的產品有個產出的前提,但也只限於前提,最後的呈現還是需要開發來實現的。

可見,開發同學在產品品質的把握上是多麼的重要。

每個IT企業裡面都有一個或一群開發,他們希望自己的程式碼可以改變世界,同時吸引軟萌妹子;他們希望通過程式碼生產工具以及類似可複用的東西,解放生產力,提高效率;他們希望自己的程式碼功能棒棒無bug, 效能卓越無匹敵。

正如之前講過的,既是優點也是侷限。重複利用的天性刻在了骨子裡,雖然中心明白設計很重要,但是,對於設計效果的實現,總會讓設計師苦笑不得,為何?

因為這本身就是矛盾的,優秀的開發講求程式碼複用、效能,然而個性化的設計就是要與眾不同,避免複用。所以,各位開發同學,如果你的團隊設計很優秀(如果設計跟你一個水平,忽略這句話), 為了產品的高品質產出,我們必須有強烈的面向設計的開發思想,首先第一點就是心理上要能夠接受,各個專案之間基本上沒法重用的web元件;其次,行動上,願意花一些額外的功夫和心思,雕琢設計的細節實現。

等最終高品質的產品出來了,內心會很充實會自豪,你會發現自己有了長足的成長,設計師MM似乎對你更友善,跟你說的話也比以前多了。

舉例與補刀

就在上個月剛剛完成了一個取色器的定製,這裡來分享下哪些是需要高階定製的,哪些是按照模組化使用的?首先下面這個是設計圖:

面向設計的半封裝web元件開發

首先,這個取色器特異性非常強,網上絕對找不出第二個取色器元件長這個樣子。所以,崇尚自然搬運工的,可以洗洗先睡了。雖然網上有很多取色器元件,我看過他們的實現,不得不說,真不怎麼樣(直接搞一張漸變圖片是要鬧怎樣)。所以,為了還原設計品質和保證元件程式碼質量,反而是高階定製來得簡單快捷。

首先,我們要分離UI內容和元件模組內容。模組內容包括:Dropdown元件(含邊界判斷),顏色轉換模組(HSL, RGB, HEX格式間顏色轉換);剩下就是UI層內容,這是需要私人定製的。沒錯,這個元件的定製工作量比一般的元件要大很多。從程式碼量來看,要五五開。

再次強調下,大家一定要摒棄“web元件完成後儘量不要動裡面程式碼”這樣過時的想法,為了滿足設計,額外的成本付出還是需要的,只是以前只在外面小打小鬧,現在是內部調整。

至於如何具體分工,因團隊結構個每個人擅長的領域不同而不同。

好,這裡,有必要加粗說一下:恰如禮服定製需要技術嫻熟的製衣工人一樣,web元件如果想走面向設計的高階定製策略,團隊裡一定要有類似的技術嫻熟的前端人員,否則會有相當高昂不划算的定製成本。

五、實踐出真知

近2個月之後……

前面提到過設計師jerry對日期時間選擇元件的諮詢,後來,莫名飛來一些蝴蝶,這個日期時間選擇元件就我來實現了,基於面向設計的半封裝理念,我是怎麼實現的呢?

  1. API分離 – 迴歸UI元件的本源 – HTML
    大家都知道,HTML5裡面,本身就是有類似datedatetime型別的input控制元件的,如Chrome瀏覽器下會自動呼叫自己的時間選擇控制元件:面向設計的半封裝web元件開發所謂UI元件,無非就是實現滿足產品氣質的統一相容的瀏覽器的那套東西。道家講求追本溯源,從這個哲學層面講,使用瀏覽器以及HTML5規範那套互動體驗,一定是最佳實踐。傳統的洋洋灑灑的JS和五花八門的API都是逆時代而行,註定要成為歷史的。因此,我這裡實現的日期時間選擇元件基於原生的規範的HTML5 input元素實現,沒錯,只能是input元素。具體包括:

    每種type列表對應一種時間選擇皮膚。例如,選年的,和選月的(終效果截圖):

    面向設計的半封裝web元件開發 面向設計的半封裝web元件開發

    不僅僅如此,可選時間範圍,甚至包括時間選擇的跨度均是通過HTML原生屬性設定完成。包括:minmaxstep等。

    min對應於傳統日期元件的startDate API, max對應於endDatevalue對應於initDate

    而這裡,我們將類別交給type, 範圍交給min/max, 從JS分離出來,交給了HTML. 即增加了元件的可讀性和可訪問性,同時,給我們的元件瘦身,可以專注於呈現本身。

    最終,我們的元件API就非常的簡練,只需要一個onShow()/onHide()回撥,使用也更加規範(因為遵循的HTML5規範),記憶與學習成本也更低。最最厲害之處在於,我們只要在common.js全域性例項化一下,例如:

    其他所有子頁面,你都不需要額外的JS, 設定額外的API。 只要按照HTML5規範,寫好HTML內容,日期時間選擇功能就槓槓地呈現在那裡。

    工作不要太輕鬆哦!

    什麼?選擇日期的回撥?

    使用者只要關心input元素本身就好了,就跟使用原生的input元素一樣,給其繫結change事件,當文字框中日期變化的時候,change事件就會自動觸發。可以說,就算沒有這個UI元件,我們的頁面功能也是可以正常使用,這就是API分離給HTML在可訪問性上的質的提升。

  2. 面向UI設計的高階定製
    UI層的東西變化性非常強,你不可能說是寫了個元件,適用於所有團隊,所有場景,那你的元件該有多大,多少邏輯判斷哈!對於某一個專案而言,是不需要的,我們需要穩固的核心,以及在這個基礎上,面向UI的高階定製。日期時間選擇比較難實現的一個皮膚就是日期範圍選擇,類似這樣:面向設計的半封裝web元件開發其實呢,要實現有此功能並且功能通用的元件,並不難,我們從網上找一下,也是可以找到的。但是呢,如果你看了設計師對選中細節的處理,你去找個可以滿足如此UI設計的元件看看,就很難了!那些細節呢?包括:

    1. 獨立選中真空;
      面向設計的半封裝web元件開發
    2. 非首尾選中實色;
      面向設計的半封裝web元件開發
    3. 首尾選中半直角半圓角;
      面向設計的半封裝web元件開發
    4. 首尾選中處於邊緣且折行則頂到邊緣且半開放;
      面向設計的半封裝web元件開發
    5. 首尾選中處於邊緣不折行則不頂到邊緣;
      面向設計的半封裝web元件開發
    6. 正常區域方方正正,選中頂到邊緣。
      面向設計的半封裝web元件開發

    咋整?顯然,面對如此UI,我們需要對元件內部實現進行簡單的定製,主要定製內容包括:

    1. 通常態類名
    2. 選中態類名
    3. 選中起始類名
    4. 選中結束類名
    5. 月初類名
    6. 月末類名
    7. 星期幾對應列類名
    於是,極端情況,這麼多類名會同時出現:
    面向設計的半封裝web元件開發

    如果我們是一個普通的日期選擇器,只要兩個類名就可以了:.ui_date_item.selected。但是,當我們面對的UI元件的樣式非常精緻的時候,我們就必須根據設計量量身定製一些類名,輔助實現我們的表現層效果。這樣的成本是必須也是必要的。

    提問?我們還需要對國家法定節假日(包括週六週日)做處理嗎?

    從元件本身強大角度講,支援自然顯得更牛,但實際上這只是開發人員自己的感覺,現代元件講求輕便靈活,如果專案沒有這樣的需求,我們就沒有必要做類似的處理;如果後期提出了需求,我們再處理之。

    這種思維方式有別於傳統的——“我需要考慮好各種使用場景,弄一個功能豐富強大的元件”;而是“UI層需要什麼,我程式碼就做什麼,儘量減少API,只考慮常用場景,生僻場景置之。”

  3. 模組化元件部分
    元件體系通用的定位模組。時間選擇器內部每種類別的皮膚也是獨立模組,分獨立呼叫也可以從其他皮膚切換呼叫。

六、最後的大總結

  1. 為了最大化元件的品質,元件的實現要講求分工;
  2. 要想分工,需要將元件UI層東西從JS剝離出來,發揮CSS/HTML工程師的在UI處理上造詣;
  3. 想要剝離,就要求元件半封裝,避開大而全的API;
  4. 所謂半封裝是功能封裝,UI不封裝;但對於某一具體專案,元件還是完全封裝的;
  5. 避開API的方法包括交給原生的HTML屬性API, 以及根據專案UI場景設計API,告別無意義的生僻場景API的使用。
  6. 發揮CSS的潛力,儘量避免使用JS做一些自己為是的功能;
  7. 面向設計的元件構建思想只適用於戰略級專案、或希望成為精品的專案,以及需要配備優秀設計和UI開發。否則傳統的大而全的元件反而更適用。
  8. UI元件的本質是HTML和CSS, JS只是輔助,千萬不要亂了主次。

最後,我們得到的就是一款UI設計精良,同時程式碼輕便簡潔,量身定製的高階web元件,配合模組化的管理,整個專案的品質就可以有質的提升。

OK, 以上就是自己對web元件的一些思考和感悟,可能講得有些囉嗦(概要版點這裡),希望不會影響中心思想的傳達。另外,大家讀完之後有什麼想法,或者本身就對web元件有一些思考,都歡迎留言討論。

最後,感謝閱讀!

相關文章