、盒子模型
下圖中可以看到,在設(shè)置width的時(shí)候,標(biāo)準(zhǔn)的盒子模型是不包括border和padding的,而在IE瀏覽器中是包括這兩項(xiàng)的。
盒模型是有兩種標(biāo)準(zhǔn)的,一個(gè)是標(biāo)準(zhǔn)模型,一個(gè)是IE模型。
標(biāo)準(zhǔn)模型中,盒模型的寬高只是內(nèi)容(content)的寬高,默認(rèn)正是W3C標(biāo)準(zhǔn)盒模型。
而在IE模型中盒模型的寬高是內(nèi)容(content)+填充(padding)+邊框(border)的總寬高。
/* 標(biāo)準(zhǔn)模型 */
box-sizing:content-box;
/*IE模型 */
box-sizing:border-box;
box-sizing:content-box padding和border都會(huì)撐開盒子,改變盒子的寬度高度
box-sizing:border-box padding和border都不會(huì)撐開盒子,不會(huì)改變盒子的寬度,盒子的內(nèi)容會(huì)相應(yīng)縮小。
2、盒子模型屬性
(1)border
border:width style color
style屬性
none 沒有邊框
solid 邊框?yàn)閷?shí)線
dashed 邊框?yàn)樘摼€
dotted 邊框?yàn)辄c(diǎn)線
double 邊框?yàn)殡p實(shí)線
表格的細(xì)線邊框合并:border-collapse:collapse
圓角邊框(CSS3):border-radius:左上角 右上角 右下角 左下角
(2)padding
可以分開設(shè)置:padding-left padding-top padding-right padding-bottom
也可以放在一起設(shè)置:padding:10px 20px 30px 40px;
順序?yàn)椤?/p>
如果設(shè)置1個(gè)值,表示四個(gè)方向是同一個(gè)值
如果設(shè)置兩個(gè)值,表示上下 右左
如果設(shè)置三個(gè)值,表示上 右左 下
(3)margin
設(shè)置方法和padding相同,可以分開設(shè)置也可以放在一起設(shè)置。
行內(nèi)元素只有左右外邊距,沒有上下外邊距。在ie6等低版本中是沒有內(nèi)邊距的。
外邊距可以實(shí)現(xiàn)盒子居中,必須滿足兩個(gè)條件:
1. 必須是塊級(jí)元素
2. 盒子必須指定寬度
然后設(shè)置左右外邊距為auto,就可以實(shí)現(xiàn)水平居中
清除元素默認(rèn)內(nèi)外邊距
padding: 0;
margin: 0;
外邊距合并
場景一:
使用margin定義塊元素的垂直外邊距時(shí),可能會(huì)出現(xiàn)外邊距的合并。當(dāng)上下相鄰的兩個(gè)塊元素相遇時(shí),如果上面的元素有margin-bottom,下面的元素有margin-top,則他們之間的垂直間距不是margin-bottom和margin-top的和,而是取兩者中的較大的值作為兩個(gè)元素的邊距,這種現(xiàn)象稱為相鄰塊元素垂直外邊距的合并。
解決方法:
避免!(如此羞澀的解決方案)
場景二:
對于兩個(gè)嵌套關(guān)系的塊元素,如果父元素沒有padding-top和border,則父元素的margin-top會(huì)與子元素的margin-top發(fā)生合并,合并后的外邊距為兩者中的較大者。
解決方法:
1. 為父元素設(shè)定1px的border或padding-top
2. 為父元素添加overflow:hidden
3、盒子陰影
box-shadow:水平位置 垂直位置 模糊距離 陰影尺寸 陰影顏色 內(nèi)/外陰影
h-shadow 必選,水平陰影的位置,允許負(fù)值
v-shadow 必選,垂直陰影的位置,允許負(fù)值
blur 可選,模糊距離
spread 可選,陰影的尺寸(影子大小)
color 可選,陰影的顏色
inset 可選,將外部陰影改為內(nèi)部陰影(外陰影為默認(rèn)屬性,不需要寫,沒有outset屬性)
本文參考自https://www.jianshu.com/p/83cfe1a343fd。
輯導(dǎo)語:如今人們已經(jīng)習(xí)慣于使用各種智能設(shè)備,然而全球有3億左右殘障人群,他們的需求不該被忽略,于是無障礙設(shè)計(jì)便應(yīng)運(yùn)而生。本文作者從色盲用戶的角度出發(fā),分享如何做色彩無障礙設(shè)計(jì),一起來學(xué)習(xí)一下吧。
隨著科技的普及和快速發(fā)展,人們越來越頻繁和習(xí)慣于使用智能設(shè)備,然而全球有3億左右的殘障人群, 無論是從科技還是法律的角度,這群人的需求不該被忽略。
于是無障礙設(shè)計(jì)應(yīng)運(yùn)而生。無障礙具體可拆分為視覺、聽覺、操作、認(rèn)知、言語交流無障礙. 而色彩是視覺中很重要的部分,我們的世界是五彩繽紛的,不同的色彩被賦予不同的意義,對于色覺障礙人群,我們該如何包容性地設(shè)計(jì),讓他們的生活更加便利和美好呢?
無障礙設(shè)計(jì)無處不在,舉個(gè)例子:Spotify有兩種播放模式,一個(gè)是隨機(jī)播放,一個(gè)是循環(huán)播放.它通過改變圖標(biāo)的顏色為綠色,表明激活狀態(tài),但是如果僅僅只是改變顏色,對于色盲用戶來說,不容易識(shí)別,因?yàn)樵觉r艷的綠色在他們看來是暗淡的:
但是加上小綠點(diǎn)之后,不去依靠顏色也很容易判斷當(dāng)前的狀態(tài):
再舉個(gè)例子:有一款名為FODMAP的應(yīng)用程序值得借鑒,FODMAP是在腸道中不能正確吸收的糖, 這是一款通過列出食物中各種含糖量,來給用戶提供飲食參考的軟件。
軟件中用紅黃綠表示不同的FODMAP等級(jí),但是這讓色盲用戶感到很困擾:
幸運(yùn)的是,這個(gè)軟件的設(shè)置中,可以打開色盲幫助選項(xiàng), 打開后你看到的界面就變成了這樣:
用顯而易見的符號(hào)替換顏色,無論對色盲用戶還是普通用戶,都很友好。
再舉個(gè)例子, 英國的在線足球網(wǎng)站在2012年時(shí)是這樣的:
色盲用戶根本無法分辨輸贏情況,此舉無疑是白白流失了全國的色盲用戶。后來,他們也意識(shí)到了問題,于是現(xiàn)在的設(shè)計(jì)時(shí)這樣的:
每個(gè)顏色色塊中填入字母,W代表贏,L代表輸,D代表平局,色盲用戶也可以輕松獲得信息。
但是目前無障礙的普及程度并不高,色盲用戶在日常生活中仍然面臨很多的問題,比如在商店買衣服問題、在線選座問題、無法使用色彩標(biāo)簽等等。本文將帶你全面地了解如何做好色彩無障礙設(shè)計(jì)。
色盲的頻率相當(dāng)高,十二分之一的高加索人(8%),二十分之一的亞洲人(5%)和25分之一的非洲男性(4%)是所謂的“紅綠”色盲。它比AB血型更常見,據(jù)統(tǒng)計(jì),平均每12名男性中就有1人有某種形式的色盲, 每200名女性中就有1人, 占人口的4.25%。麥當(dāng)勞每天為300萬色盲客戶提供服務(wù)。亞馬遜每天超過110萬客戶是色盲。
色盲遠(yuǎn)比我們想象中的數(shù)量要龐大的多,所以設(shè)計(jì)色盲友好的互聯(lián)網(wǎng)產(chǎn)品,這件事情應(yīng)當(dāng)被重視和完善。
正常的彩色視覺需要用到三種功能正常的錐形細(xì)胞,紅色、綠色和藍(lán)色錐形細(xì)胞,根據(jù)三色錐形細(xì)胞的是否缺失,又可以將色盲分為全色盲,雙色色盲和三色色盲。
三色色盲擁有三種錐形細(xì)胞, 但是其中一種錐細(xì)胞感知的光略微偏離對齊,根據(jù)哪種錐形細(xì)胞類型“有缺陷”,產(chǎn)生三種不同類型的效果,并且還具有不同的嚴(yán)重性。
三種情況分別是是紅色弱,即對紅光的敏感性降低,綠色弱: 對綠光(最常見的色盲形式)的敏感性降低,以及藍(lán)色弱: 對藍(lán)光的敏感性降低(極為罕見,只有0.001%的發(fā)生率)。
對某種類型光的感知力,有敏感性降低的,也有完全感知不到的,程度不一。
因?yàn)榧t色和綠色錐形細(xì)胞感知到的光譜部分明顯重疊,因此紅色和綠色色弱都難以分辨紅色、綠色、褐色和橙色, 所以在診斷的時(shí)候常常被統(tǒng)稱為“紅綠色盲”,他們對藍(lán)色和紫色以及多種顏色的組合也常常難以區(qū)分。
藍(lán)色弱很難分辨藍(lán)色VS黃色,紫羅蘭VS紅色,藍(lán)色VS綠色. 藍(lán)色弱眼中是紅粉色,黑白色和青綠色的世界。
1)紅色色弱
2)綠色色弱
3)藍(lán)色色弱
雙色色盲只有兩種顏色的錐形細(xì)胞,第三種類型的細(xì)胞完全缺失. 所以,紅色盲完全無法感知到紅色,綠色盲完全無法感知到綠色,藍(lán)色盲完全無法感知到藍(lán)色。
同時(shí)喪失了紅色和綠色感知力的人生活在暗綠色的世界,所以藍(lán)色和黃色會(huì)非常突出。
大約1/2的三色色盲看到的世界與雙色色盲看到的很相似,但是三色色盲色彩感知力受光照影響較大,在良好的光照下,他們對色彩的感知力就更好,反之久更糟糕。總的來說, 雙色色盲在辨別色彩方面比三色色盲更容易些。
為了讓大家更清晰的了解不同色盲眼中的世界,這里做一些展示:
1)紅色色盲
2)綠色色盲
3)藍(lán)色色盲
全色盲完全沒有任何一種顏色細(xì)胞,他們眼中世界是完全的黑白色,就像是黑白電視機(jī)那樣.但是我們在做產(chǎn)品無障礙時(shí),基本不會(huì)考慮這一類人群,因?yàn)槿ぐl(fā)生的概率實(shí)在是太低了,33000人中僅有1人,他們的生活因此有很多阻礙,在正常的光照條件下,也需要戴深色墨鏡。
WAI制定了幾項(xiàng)W3C建議,包括:
WCAG有三種評(píng)級(jí): A、AA和AAA,標(biāo)準(zhǔn)從低到高:
WCAG2.1詳細(xì)指南完整版可查看: https://www.w3.org/TR/WCAG21/
快速參考WCAG標(biāo)準(zhǔn): https://www.w3.org/WAI/WCAG21/quickref/?currentsidebar=%23col_overview#use-of-color
WCAG關(guān)于顏色的要求描述:https://www.w3.org/WAI/WCAG21/Understanding/use-of-color.html
WCAG中將字體分為一般字體和大字體。
大字體是這樣定義的:“大于等于18點(diǎn)常規(guī)體或者大于等于14點(diǎn)的粗體,如果是中日韓的語言,就要換算成同等大小”,除卻大字體之外的就是一般文字。
AA評(píng)級(jí)對于一般文字來說,文字和背景的顏色對比度不少于4.5:1的對比度;對于大字體和(如圖標(biāo)、表格等等)組件的要求就沒那么嚴(yán)格,只要顏色對比不低于3:1即可。
如果帶有文本的按鈕也有彩色邊框,因?yàn)檫吙驔]有提供輔助信息,所以對邊框沒有對比度要求,只要該文字符合AA評(píng)級(jí)即可。
顏色在特定的語境中,會(huì)被賦予特殊的含義,如常見的紅色代表警告,綠色代表合格通過的意思等等,而患有色彩缺陷、視力衰退的老齡化群體、還有使用單色閱讀器(如kindle紙墨水)的人都可能會(huì)因此遺漏了顏色所傳達(dá)出的重要信息。
同時(shí)在用顏色表達(dá)某種信息時(shí),為了確保所有的用戶都能接受到信息,需要添加另一種視覺形式,下面給大家舉例說明:
1)文字
文字是最容易讓色盲用戶了解到顏色含義的元素,也是我們首先會(huì)考慮到的。
一個(gè)典型例子是表單字段上的錯(cuò)誤狀態(tài), 紅色通常用于表示文本字段中的錯(cuò)誤, 但是標(biāo)紅不足以引起色盲用戶的注意,因?yàn)閺乃麄兊囊暯强矗?紅色的字體在一群黑色的字體中顯得很暗, 很難分辨出來。因此,你需要一個(gè)額外的提示,例如文本或圖標(biāo),來指示錯(cuò)誤狀態(tài)。
2)圖標(biāo)
圖標(biāo)是使用頻率很高的組件, 一些通用圖標(biāo)的含義甚至不需要Tooltip來解釋,用戶就能一眼識(shí)別, 比如設(shè)置、警告、成功等等圖標(biāo),舉個(gè)例子:許多B端界面會(huì)通過不同的語義顏色,告知用戶某個(gè)流程的狀態(tài),但是對于色盲用戶來說,識(shí)別顏色對應(yīng)的狀態(tài)圖例是一件很艱難的事情,但是如果添加圖標(biāo)輔助信息,一切就變得容易多了!
3)明暗對比
這一點(diǎn)常常被大家忽略.如果兩種顏色的色調(diào)不同,但是擁有強(qiáng)烈的明暗對比,那么在這里, 明暗對比也算是另一種視覺輔助形式,只要這兩種顏色的對比不低于3:1(AA)。
只有一種情況例外, 就是用戶需要準(zhǔn)確地識(shí)別一種特定的顏色,這個(gè)時(shí)候?qū)Ρ榷染筒荒芩阍趦?nèi)。
4)符號(hào)
舉個(gè)例子,標(biāo)注紅色的文字標(biāo)簽是必填項(xiàng),出于無障礙的需要,我們可以在紅色標(biāo)簽上打一個(gè)星號(hào),這樣即使注意不到顏色差異,看到星號(hào)也會(huì)意識(shí)到此項(xiàng)必填。
但是!大多數(shù)情況下,星號(hào)的尺寸很小(位于左上角),不容易被屏幕閱讀器捕捉到,為了改善這樣的情況,設(shè)計(jì)者可以增大星號(hào)的尺寸,以及為星號(hào)添加注釋(Tooltip), 這個(gè)注釋是由開發(fā)者完成的, 不借助屏幕閱讀器是無法捕捉這個(gè)信息。
5)數(shù)字
這是一個(gè)丙烯結(jié)構(gòu)式,三個(gè)碳原子被標(biāo)上了三種顏色(化學(xué)老師會(huì)教我們標(biāo)記碳原子序號(hào)的規(guī)律,不過就假設(shè)這是老師在給一群初學(xué)者的課件吧),那么老師提問“黃色的碳原子和紫色的碳原子中間用的是什么鍵”,色盲學(xué)生可能就沒辦法辨別顏色所對應(yīng)的碳原子了,但是如果標(biāo)上序號(hào),這樣提問:“1號(hào)碳原子和2號(hào)碳原子中間用的是什么鍵?”,是不是所有的學(xué)生就一目了然了?
6)圖形
減少使用顏色的數(shù)量,增加圖形樣式,這樣盲人用戶能夠花費(fèi)更少的力氣在辨別顏色上。
7)圖案
在顯示圖形或者圖表時(shí),可以提供一些圖案供用戶填充,色盲雖然對顏色不敏感,但是對于圖案卻非常容易察覺區(qū)別。
這里推薦幾個(gè)提供大量圖案樣式的網(wǎng)站:Http://pattern.monster
交互式地圖(付費(fèi)使用):https://www.arcgis.com/index.html
Figma圖案填充插件:Hero Pattern for Image https://www.figma.com/community/plugin/743134103711120154
以折線圖舉例:
再以堆疊條形圖為例:
再舉個(gè)倫敦地鐵圖和上海地鐵圖的例子:
WCAG的標(biāo)準(zhǔn)被許多人奉為無障礙法則,但是有些情況下,并不適用。舉個(gè)例子:你覺得黑色字體和白色字體在橙色的背景上,哪一種看起來更清晰?
相信有不少人覺得白色字體看起來更舒服,更清晰,但是WCAG的顏色標(biāo)準(zhǔn)卻告訴我們,黑色達(dá)到了AAA的級(jí)別,而白色卻連AA級(jí)別都沒有達(dá)到:
不僅僅是我們,在很早之前,就有設(shè)計(jì)師對此產(chǎn)生疑惑,并做了用戶調(diào)研。
Ericka Seastrand 曾在2019年做過一項(xiàng)用戶調(diào)研,調(diào)研對象是20名色盲用戶,測試問題是: 黑色還是白色的字體在該背景下更突出? 最后的結(jié)果顯示: 61%的用戶認(rèn)為白色字體更清晰。
這些用戶也給出了具體的原因:
所以謹(jǐn)記:盡信書,則不如無書。WCAG的標(biāo)準(zhǔn)僅供參考,但是實(shí)際運(yùn)用中,應(yīng)當(dāng)以用戶的感受為參考,質(zhì)疑精神是很可貴的!
1)灰色按鈕
有些人認(rèn)為不能夠使用灰色的按鈕,因?yàn)榛疑o人以不可用的暗示,但是其實(shí)并沒有領(lǐng)悟不可用狀態(tài)的本質(zhì). 視覺深度才是幫助用戶判斷按鈕狀態(tài)的核心.活動(dòng)狀態(tài)是通過顏色對比度而不是色調(diào)傳達(dá)的。
正常狀態(tài)的按鈕的文字與背景對比起來,看上去更接近和占主導(dǎo)地位,而不可用狀態(tài)缺乏對比度,文字看起來在更遠(yuǎn)的地方。不過灰色按鈕經(jīng)常被用作二級(jí)按鈕,主按鈕都是需要使用彩色。
同樣地,按鈕的各種交互狀態(tài),只要對比度有差異性,能夠傳達(dá)視覺深度變化,就是符合無障礙的標(biāo)準(zhǔn)的,以Ant Design舉例:
2)讓你的主按鈕最顯眼
在大多數(shù)情況下,設(shè)計(jì)師們都是通過賦予主按鈕顏色,吸引用戶注意,但是在色盲用戶眼中,主按鈕的顏色差異很難被捕捉到,甚至在有些色盲眼中無法分辨顏色:
為了增加主按鈕和次按鈕的對比, 這個(gè)時(shí)候我們可以嘗試:
當(dāng)你在為你的產(chǎn)品或者品牌選擇色彩時(shí),一定要避免下面的色彩組合:
網(wǎng)頁中超鏈接文本很常見,比如百度百科,如果只是用顏色區(qū)別超鏈接,對于有些色盲很難注意到這是一個(gè)超鏈接,他需要將鼠標(biāo)滑過時(shí),發(fā)現(xiàn)變成一只手,才能知道。
所以對于超鏈接文本,添加下劃線是一個(gè)很好的方式:
曾經(jīng)看過一個(gè)色盲講述自己買衣服的難題, 他來到商場,看到一件衣服,但是不確定這個(gè)衣服是什么顏色,可是衣服上的標(biāo)簽也沒有寫顏色,所以他只好硬著頭皮去問商店里其他的人,承受著一些不解和懷疑的目光,如果這件衣服有清晰的顏色標(biāo)簽的話,就能輕松解決這個(gè)問題了。這一點(diǎn)對于購物網(wǎng)站來說,尤其重要。
1. 避免文本和對象被背景遮擋的情況。 例如,文本/對象和背景之間的亮度和飽和度應(yīng)該有足夠的對比度。避免組合亮度相同但色調(diào)不同的顏色。例如,綠色背景上的紅色字符對色盲來說是不可讀的。在深色背景上使用明亮的文本/對象,反之亦然。
2. 文本和對象盡可能粗或大,色盲人很難區(qū)分細(xì)線和小符號(hào)的顏色, 對于彩色文本,一定要使用粗體字體。
3. 小心使用紅色和綠色,對于視覺正常的人來說,純紅色是明亮生動(dòng)的顏色。但對于色盲來說,它就像藍(lán)色或深綠色一樣暗淡。特別是對于紅色盲來說,深紅色看起來幾乎是黑色的。因此,避免在黑色背景上使用紅色字符,包括黑板。但是有一些紅色對色盲來說是鮮活的, 比如:
避免使用純綠色,使用偏藍(lán)一點(diǎn)的綠色。
4. 在深藍(lán)色背景上無法看清:深紅色、明亮的紫紅色、細(xì)線條。
5. 在一堆黑色字體中,很難看到深紅色強(qiáng)調(diào)的字體。
6. 盡量減少顏色的數(shù)量,可以使用不同的外形和少量容易識(shí)別的顏色的組合。
7. 保持顏色色調(diào)的對比的同時(shí),也可以添加亮度的對比。
8. 使用種類少且容易識(shí)別的字體。
盡量不要使用顏色的名字交流信息. 在演講時(shí),去指代ppt上的某個(gè)東西時(shí),不要說“那個(gè)紅色的細(xì)胞”,嘗試描述除了顏色信息之外的,比如“那個(gè)紅色的方形的位于PPT左上角的細(xì)胞”。
Stark: 色盲模擬器和顏色對比度檢查器網(wǎng)站, sketch/figma/XD插件 https://www.getstark.co
Color Oracle: 一款免費(fèi)的色盲模擬軟件,支持Windows,Mac 和 Linux. https://colororacle.org
Sim Daltonism: 一款色盲模擬軟件,可以選擇不同類型的色盲.只有mac版本. https://michelf.ca/projects/mac/sim-daltonism/
Toptal:一款在線模擬色盲工具. https://www.toptal.com/designers/colorfilter
Color-contrast-checker: 顏色對比度檢查器,提供快速調(diào)節(jié), figma插件 https://www.figma.com/community/plugin/733159460536249875/A11y—Color-Contrast-Checker
Tanaguru Contrast Finder: 檢測顏色對比度,如果你的顏色沒有達(dá)到要求,還會(huì)提供新顏色建議. https://contrast-finder.tanaguru.com
Color Review: 提供兩種顏色組合在一起的預(yù)覽,檢測結(jié)果失敗還會(huì)提供顏色建議https://color.review
color contrast checker from polypane: 提供顏色對比和修改建議. https://polypane.app/color-contrast
Accessible colors: 提供顏色對比、修改建議、還可以輸入字體大小和字重. https://accessible-colors.com
Accessible color palette builder:選擇5個(gè)顏色,網(wǎng)站會(huì)通過分析這些的顏色的排列組合,判斷你的色板是否符合無障礙標(biāo)準(zhǔn)https://toolness.github.io/accessible-color-matrix
contrast grid:通過在左側(cè)邊欄手動(dòng)添加/刪減行列、編輯行列的色值,為您提供這些顏色排列組合的對比度結(jié)果,非常高效而且一目了然https://contrast-grid.eightshapes.com
Cloudflare color tool:當(dāng)你不知道選擇什么顏色毫無頭緒時(shí),你可以嘗試這個(gè)網(wǎng)站!它會(huì)幫你提取來自某個(gè)鏈接、某個(gè)圖片的顏色色板,當(dāng)然你也能輸入色值.然后把這些顏色拖到對應(yīng)的功能(底色、主色、背景色、描邊色),你就可以預(yù)覽下你的產(chǎn)品用了這個(gè)色板大概是什么樣子了.它同時(shí)也提供這些顏色的排列組合分析https://color.cloudflare.design
少數(shù)群體如色盲、老齡化群體、殘障群體等等,在近些年來,他們對無障礙使用互聯(lián)網(wǎng)的需求,越來越受到關(guān)注,也許你在現(xiàn)在不需要無障礙技術(shù)的幫助,但是隨著你變老,在未來的某個(gè)階段也許無障礙技術(shù)就會(huì)大大的幫助你。
色彩無障礙只是無障礙的一小步,但是卻是證明無障礙普及進(jìn)步的一大步。
參考文章:
https://medium.com/inside-design/a-guide-to-color-accessibility-in-product-design-516e734c160c
https://www.colourblindawareness.org/colour-blindness/types-of-colour-blindness
https://modus.medium.com/the-myths-of-color-contrast-accessibility-4b7fcba77317
https://jfly.uni-koeln.de/color
https://www.bounteous.com/insights/2019/03/22/orange-you-accessible-mini-case-study-color-ratio
本文由郝小七指導(dǎo)http://www.woshipm.com/u/917803
本文由 @自來卷夏憶 原創(chuàng)發(fā)布于人人都是產(chǎn)品經(jīng)理,未經(jīng)許可,禁止轉(zhuǎn)載
題圖來自 Unsplash,基于 CC0 協(xié)議
gt; 這是一篇有故事的文章 --- 來自一個(gè)weex在生產(chǎn)環(huán)境中相愛相殺的小碼畜..故事一: Build
雖然
weex
的口號(hào)是
一次撰寫 多端運(yùn)行
, 但其實(shí)
build
環(huán)節(jié)是有差異的,
native
端構(gòu)建需要使用
weex-loader
, 而
web
端則是使用
vue-loader
,除此以外還有不少差異點(diǎn), 所以
webpack
需要兩套配置.
最佳實(shí)踐
使用
webpack
生成兩套
bundle
,一套是基于
vue-router
的
web spa
, 另一套是
native
端的多入口的
bundlejs
首先假設(shè)我們在
src/views
下開發(fā)了一堆頁面
build web配置
web端的入口文件有
render.js
import weexVueRenderer from 'weex-vue-render'Vue.use(weexVueRenderer)
main.js
import App from './App.vue'import VueRouter from 'vue-router'import routes from './routes'Vue.use(VueRouter)
App.vue
<template>
webpack.prod.conf.js
入口
const webConfig = merge(getConfig('vue'), {
build native配置
native端的打包流程其實(shí)就是將
src/views
下的每個(gè)
.vue
文件導(dǎo)出為一個(gè)個(gè)單獨(dú)的
vue
實(shí)例, 寫一個(gè)
node
腳本即可以實(shí)現(xiàn)
// build-entry.js
// build-entry.js require('shelljs/global') const path = require('path') const fs = require('fs-extra') const srcPath = path.resolve(__dirname, '../src/views') // 每個(gè).vue頁面 const entryPath = path.resolve(__dirname, '../entry/') // 存放入口文件的文件夾 const FILE_TYPE = '.vue' const getEntryFileContent = path => { return `// 入口文件 import App from '${path}${FILE_TYPE}' /* eslint-disable no-new */ new Vue({ el: '#root', render: h => h(App) }) ` } // 導(dǎo)出方法 module.exports = _ => { // 刪除原目錄 rm('-rf', entryPath) // 寫入每個(gè)文件的入口文件 fs.readdirSync(srcPath).forEach(file => { const fullpath = path.resolve(srcPath, file) const extname = path.extname(fullpath) const name = path.basename(file, extname) if (fs.statSync(fullpath).isFile() && extname === FILE_TYPE) { //寫入vue渲染實(shí)例 fs.outputFileSync(path.resolve(entryPath, name + '.js'), getEntryFileContent('../src/views/' + name)) } }) const entry = {} // 放入多個(gè)entry fs.readdirSync(entryPath).forEach(file => { const name = path.basename(file, path.extname(path.resolve(entryPath, file))) entry[name] = path.resolve(entryPath, name + '.js') }) return entry }
webpack.build.conf.js
中生成并打包多入口
const buildEntry = require('./build_entry') // .. // weex配置 const weexConfig = merge(getConfig('weex'), { entry: buildEntry(), // 寫入多入口 output: { path: path.resolve(distPath, './weex'), filename: 'js/[name].js' // weex環(huán)境無需使用hash名字 }, module: { rules: [ { test: /\.vue$/, loader: 'weex-loader' } ] } }) module.exports = [webConfig, weexConfig]
最終效果
故事二: 使用預(yù)處理器
在
vue
單文件中, 我們可以通過在
vue-loader
中配置預(yù)處理器, 代碼如下
{ test: /\.vue$/, loader: 'vue-loader', options: { loaders: { scss: 'vue-style-loader!css-loader!sass-loader', // <style> sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax' // <style> } } }
而
weex
在native環(huán)境下其實(shí)將
css
處理成
json
加載到模塊中, 所以...
使用
vue-loader
配置的預(yù)處理器在web環(huán)境下正常顯示, 在
native
中是無效的
native環(huán)境下不存在全局樣式, 在js文件中
import 'index.css'
也是無效的
解決問題一
研究
weex-loader
源碼后發(fā)現(xiàn)在
.vue
中是無需顯示配置
loader
的, 只需要指定
<style>
并且安裝
stylus stylus-loader
即可,
weex-loader
會(huì)根據(jù)
lang
去尋找對應(yīng)的
loader
. 但因?yàn)?/p>
scss
使用
sass-loader
, 會(huì)報(bào)出
scss-loader not found
, 但因?yàn)?/p>
sass
默認(rèn)會(huì)解析
scss
語法, 所以直接設(shè)置
lang="sass"
是可以寫
scss
語法的, 但是
ide
就沒有語法高亮了. 可以使用如下的寫法
<style> @import './index.scss' </style>
語法高亮, 完美!
解決問題二
雖然沒有全局樣式的概念, 但是支持單獨(dú)
import
樣式文件
<style lang="sass">
故事三: 樣式差異
這方面官方文檔已經(jīng)有比較詳細(xì)的描述, 但還是有幾點(diǎn)值得注意的
簡寫
weex
中的樣式不支持簡寫, 所有類似
margin: 0 0 10px 10px
的都是不支持的
背景色
android
下的view是有白色的默認(rèn)顏色的, 而iOS如果不設(shè)置是沒有默認(rèn)顏色的, 這點(diǎn)需要注意
浮點(diǎn)數(shù)誤差
weex
默認(rèn)使用
750px * 1334px
作為適配尺寸, 實(shí)際渲染時(shí)由于浮點(diǎn)數(shù)的誤差可能會(huì)存在幾
px
的誤差, 出現(xiàn)細(xì)線等樣式問題, 可以通過加減幾個(gè)
px
來調(diào)試
嵌套寫法
即使使用了預(yù)處理器,
css
嵌套的寫法也是會(huì)導(dǎo)致樣式失效的
故事四: 頁面跳轉(zhuǎn)
weex
下的頁面跳轉(zhuǎn)有三種形式
native -> weex
:
weex
頁面需要一個(gè)控制器作為容器, 此時(shí)就是
native
間的跳轉(zhuǎn)
weex -> native
: 需要通過module形式通過發(fā)送事件到native來實(shí)現(xiàn)跳轉(zhuǎn)
weex -> weex
: 使用navigator模塊, 假設(shè)兩個(gè)
weex
頁面分別為
a.js, b.js
, 可以定義
mixin
方法
function isWeex () { return process.env.COMPILE_ENV === 'weex' // 需要在webpack中自定義
這樣就組件里使用
this.push(url), this.pop()
來跳轉(zhuǎn)
跳轉(zhuǎn)配置
iOS下頁面跳轉(zhuǎn)無需配置, 而
android
是需要的, 使用
weexpack platform add android
生成的項(xiàng)目是已配置的, 但官方的文檔里并沒有對于已存在的應(yīng)用如何接入進(jìn)行說明
其實(shí)
android
中是通過
intent-filter
來攔截跳轉(zhuǎn)的
<activity
然后我們新建一個(gè)
WXPageActivity
來代理所有
weex
頁面的渲染, 核心的代碼如下
[@Override](/user/Override) protected void onCreate(Bundle saveInstanceState) { // ...
順便說下...
weex
官方?jīng)]有提供可定制的
nav
組件真的是很不方便..經(jīng)常需要通過
module
橋接
native
來實(shí)現(xiàn)跳轉(zhuǎn)需求
來自@荔枝我大哥 的補(bǔ)充
安卓和蘋果方面可以在原生代碼接管`navigator`這個(gè)模塊,安卓方面只需要實(shí)現(xiàn)`IActivityNavBarSetter`,蘋果方面好像是`WXNavigatorProtocol`,然后在app啟動(dòng)初始化weex時(shí)注冊即可。
故事五: 頁面間數(shù)據(jù)傳遞
native -> weex
: 可以在
native
端調(diào)用
render
時(shí)傳入的
option
中自定義字段, 例如
NSDictary *option = @{@"params": @{}}
, 在
weex
中使用
weex.config.params
取出數(shù)據(jù)
weex -> weex
: 使用storage
weex -> native
: 使用自定義module
故事六: 圖片加載
官網(wǎng)有提到如何加載網(wǎng)絡(luò)圖片 但是加載本地圖片的行為對于三端肯定是不一致的, 也就意味著我們得給
native
重新改一遍引用圖片的路徑再打包...
但是當(dāng)然是有解決辦法的啦
Step 1
webpack
設(shè)置將圖片資源單獨(dú)打包, 這個(gè)很easy, 此時(shí)
bundleJs
訪問的圖片路徑就變成了
/images/..
{
Step 2 那么現(xiàn)在我們將同級(jí)目錄下的js文件夾與images文件夾放入
native
中, iOS中一般放入
mainBundle
, Android一般放入
src/main/assets
, 接下來只要在
imgloader
接口中擴(kuò)展替換本地資源路徑的代碼就ok了
iOS
代碼如下:
- (id<WXImageOperationProtocol>)downloadImageWithURL:(NSString *)url imageFrame:(CGRect)imageFrame userInfo:(NSDictionary *)options completed:(void (^)(UIImage *, NSError *, BOOL))completedBlock{ if ([url hasPrefix:@"http://"]) {
Android
代碼如下:
[@Override](/user/Override) public void setImage(final String url, final ImageView view,
故事七: 生產(chǎn)環(huán)境的實(shí)踐
增量更新
方案一
可以使用google-diff-match-patch來實(shí)現(xiàn), google-diff-match-patch擁有許多語言版本的實(shí)現(xiàn), 思路如下:
服務(wù)器端構(gòu)建一套管理前端
bundlejs
的系統(tǒng), 提供查詢
bundlejs
版本與下載的api
客戶端第一次訪問
weex
頁面時(shí)去服務(wù)端下載
bundlejs
文件
每次客戶端初始化時(shí)靜默訪問服務(wù)器判斷是否需要更新, 若需更新, 服務(wù)器端
diff
兩個(gè)版本的差異, 并返回
diff
,
native
端使用
patch api
生成新版本的
bundlejs
方案二
來自 @荔枝我大哥的補(bǔ)充
我們所有的jsBundle全部加載的線上文件,通過http頭信息設(shè)置`E-Tag`結(jié)合`cache-control`來實(shí)現(xiàn)緩存策略,最終效果就是,A.vue -> A.js, app第一次加載A.js是從網(wǎng)絡(luò)下載下來并且保存到本地,app第二次加載A.js是直接加載的保存到本地的 A.js文件,線上A.vue被修改,A.vue -> A.js, app第三次加載A.js時(shí)根據(jù)緩存策略會(huì)知道線上A.js 已經(jīng)和本地A.js 有差異,于是重新下載A.js到本地并加載. (整個(gè)流程通過http緩存策略來實(shí)現(xiàn),無需多余編碼,參考https://developers.google.cn/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=zh-cn)
還可以參考很多ReactNative的成熟方案, 本質(zhì)上都是js的熱更新
降級(jí)處理
一般情況下, 我們會(huì)同時(shí)部署一套
web
端界面, 若線上環(huán)境的
weex
頁面出現(xiàn)bug, 則使用webview加載
web
版, 推薦依賴服務(wù)端api來控制降級(jí)的切換
總結(jié)
weex
的優(yōu)勢: 依托于
vue
, 上手簡單. 可以滿足以
vue
為技術(shù)主導(dǎo)的公司給
native
雙端提供簡單/少底層交互/熱更新需求的頁面的需求
weex
的劣勢: 在
native
端調(diào)整樣式是我心中永遠(yuǎn)的痛.. 以及眾所周知的生態(tài)問題, 維護(hù)組沒有花太多精力解答社區(qū)問題, 官方文檔錯(cuò)誤太多, 導(dǎo)致我在看的時(shí)候就順手提了幾個(gè)PR(逃
對于文章中提到的沒提到的問題, 歡迎來和筆者討論, 或者參考我的weex-start-kit, 當(dāng)然點(diǎn)個(gè)star也是極好的
*請認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。