摘要:我們來看看文檔上是怎么說的吧在中,你并不需要學習什么特殊的語法來定義樣式。我們仍然是使用來寫樣式。這些樣式名基本上是遵循了上的的命名,只是按照的語法要求使用了駝峰命名法,例如將改為。
我遇到了什么問題?
不久之前我重構了一個古老的項目,總結了一些js方面的想法,不過對于一個前端項目而言不僅僅只由js組成的嘛,上學的時候老師和我說HTML+CSS+JS對應的是頁面的骨架、皮膚和肌肉。既然骨架我們有了,肌肉也聊完了,今天我們就來聊聊“皮膚”吧。
由于我重構的是一個react-native項目,所以我們先來說說在react-native上是怎么寫樣式的吧,和傳統(tǒng)的web不一樣的是,在react-native上面是沒有css代碼,不過得益于Yoga,我們可以在客戶端上像寫css一樣的去書寫我們的樣式。我們來看看react-native文檔上是怎么說的吧:
在React Native中,你并不需要學習什么特殊的語法來定義樣式。我們仍然是使用JavaScript來寫樣式。所有的核心組件都接受名為style的屬性。這些樣式名基本上是遵循了web上的CSS的命名,只是按照JS的語法要求使用了駝峰命名法,例如將background-color改為backgroundColor。style屬性可以是一個普通的JavaScript對象。這是最簡單的用法,因而在示例代碼中很常見。你還可以傳入一個數(shù)組——在數(shù)組中位置居后的樣式對象比居前的優(yōu)先級更高,這樣你可以間接實現(xiàn)樣式的繼承。
沒錯,你幾乎不需要什么成本就可以按照寫css一樣的寫法去寫我們的rn樣式,我們來看一下文檔中的例子:
import React, { Component } from "react"; import { AppRegistry, StyleSheet, Text, View } from "react-native"; export default class LotsOfStyles extends Component { render() { return (); } } const styles = StyleSheet.create({ bigblue: { color: "blue", fontWeight: "bold", fontSize: 30, }, red: { color: "red", }, }); AppRegistry.registerComponent("LotsOfStyles", () => LotsOfStyles); just red just bigblue bigblue, then red red, then bigblue
在上面的demo中,我們有兩種方式去寫我們的樣式,它和我們在寫css時候遇到的外聯(lián)式樣式、內聯(lián)式樣式很相似,而項目中我們總是習慣將樣式和頁面分離,然后把他們都放在另外一個style.js文件中。這是個非常不錯的習慣,但是也造成了一些困擾。
面對一個頁面,我該怎么去模塊化它的樣式呢?在之前的項目中雖然做到了樣式和頁面的分離,讓頁面“看起來”干凈了很多,但是在 style.js 文件中仍然是雜亂的代碼,大量重復的變量、重復的內容、重復的聲明。。。這個時候又有同學說了,我們可以把這些公共的變量、代碼分離出來放到一個主題文件中呀,于是項目中除了各個頁面的style.js之外又在全局出現(xiàn)了一個theme.js文件,在這里大家愉快的把諸如顏色、大小、布局等公共的代碼放了進來。
這看似解決了style.js里重復冗余的代碼,但是也會讓我的import變得混亂:
import { StyleSheet } from "react-native"; import { px, COLOR_BG_RED, COLOR_BG_GREEN, STYLE_FR_VC_HSB, STYLE_FR_VC_HC, STYLE_FR_VC_HFS, } from "MyStyle"; export default StyleSheet.create({ // TODO });
看到這里,我想你除了知道我import進來了兩個顏色之外,對于其它變量會一頭霧水吧,除非你去MyStyle模塊里面親眼看一下才會知道真正引入進來的是些什么了,如果這里的樣式特別的多的話,除了再新建一個sytle.js之外,你就只能每次回到頭部去看看自己引入了些什么。這是我不能忍受的。。。
為你的樣式分類除了由于一次性引入太多的公共樣式導致我要來回滑動之外,當我再去寫一個新的styel.js文件時,復制這么多引入也是一件頭疼的事情,那么我能不能每次只需要寫一行import呢?如果我的樣式都是按固定規(guī)則分類放好的是不是每次就可以只import這幾個類了呢?
經常寫css的同學一定注意過樣式的書寫順序,某一類的屬性寫在一起,雖然在web中,這樣寫是為了優(yōu)化css引擎,但是這也體現(xiàn)出了樣式是有一定類型的,控制顏色的、控制邊距的、控制布局的,那么我們的公共變量是不是也可以按照這樣的規(guī)則來聲明呢?
import { color, size, layout } from "MyStyle";
這樣我們文件的頭部是不是就清晰多了呢?在寫代碼的時候,也不需要再關心我之前引入了些什么了,只要只要關注我們要寫什么就行了:
export default StyleSheet.create({ lines: { height: px(88), backgroundColor: color.background, borderLeftWidth: size.border, borderRightWidth: size.border, borderBottomWidth: size.border, borderColor: color.border, // 子元素橫向排列,垂直居中,水平分布,中間用空格填滿,最兩邊元素各自靠邊 ...layout.flex.vchbs, }, });
在我的項目中默認邊框的大小就是一個像素(1px),那么只要在最外層聲明了 size.border的大小,后面寫代碼的時候就可以暢行無阻的書寫下去了,其實我們已經模塊化了,只是我們還不夠徹底,不徹底就代表著我們的代碼不完美,而且可復用性差,就如上面的demo,如果我們這里需要一個三面的邊框,那么其它組件需不需要呢?如果需要的話是不是也可以像我這樣寫呢?
當然是不可以!為什么?因為我們是在復用這個邊框,所以我們就不該再寫一份一模一樣的代碼了,而是應該寫類似這樣的:
export default StyleSheet.create({ lines: { height: px(88), backgroundColor: color.background, // 一個邊框粗細為1px的紅色邊框 ...layout.border // 子元素橫向排列,垂直居中,水平分布,中間用空格填滿,最兩邊元素各自靠邊 ...layout.flex.vchbs, }, });
這樣我們的代碼不僅少了很多,結構也清楚了,而且到時候替換或者修改的時候也容易一些了,不過寫成這樣就結束了嘛?當然不是了,我們現(xiàn)在有一個紅色的邊框,所以我們在layout模塊下新增了一個border屬性,那么如果我們有一個藍色的邊框呢?一個綠色的粗邊框呢?我們會一直往layout模塊上新增屬性嘛?那最后你知道layout上面究竟有多少屬性嘛?那不就又回到一開始了嘛。。。
所以,我的建議是,處于根節(jié)點的模塊最好控制在3個左右:
color:用于存放整個項目的全部顏色,這也代表著,在組件的style內部,我們不應該再顯示的書寫諸如backgroundColor: "#fff"這樣的代碼了。
size:用于存放整個項目的通用大小,比如說行高、間距、字體大小等公共的數(shù)值參數(shù)。
layout:用于存放整個項目的公共布局,例如控制布局的flex屬性、通用的padding、margin、position定位。
那么第二級中的屬性我也建議控制在5個左右:
顏色:邊框顏色、背景顏色、字體顏色。。。
大小:邊框大小、間距大小、字體大小。。。
布局:flex布局、position定位。。。
這樣雖然增加了深度,但是分類清晰,結構明確,復用性也比較高。雖然可能會增加項目新建時的成本(創(chuàng)建各種分類),但是會給后續(xù)的開發(fā)、遷移、重構、復用等帶來極大的便捷。但這就結束了嘛?有的同學和我說,我有很多的邊框啊,我有很多樣式要復用啊,到最后我的layout也會大到看不懂啊。。。還有的同學說我沒有那么多可復用的樣式啊,那是不是你總結的思路就用不上了啊。當然不是咯,我們只完成了樣式模塊化的第一步(抽離樣式),接下來開始第二步。
該怎么更便捷的寫樣式?現(xiàn)在很多web開發(fā)者在書寫css的時候已經不再去寫原生的css了吧,而是采用例如scss、less這樣的預編譯語言去寫樣式了,那么這些預編譯語言給我們帶來了哪些方便呢?我想大多數(shù)同學第一時間都會想到Mixin。
利用混合器,可以很容易地在樣式表的不同地方共享樣式。如果你發(fā)現(xiàn)自己在不停地重復一段樣式,那就應該把這段樣式構造成優(yōu)良的混合器,尤其是這段樣式本身就是一個邏輯單元,比如說是一組放在一起有意義的屬性。
在react-native上面,我們的樣式代碼是js代碼,所以很天然的就自帶預編譯,不需要其它額外的語言去處理它,要做的只是判斷你的屬性是否需要一個Mixin。
判斷一組屬性是否應該組合成一個混合器,一條經驗法則就是你能否為這個混合器想出一個好的名字。如果你能找到一個很好的短名字來描述這些屬性修飾的樣式,比如rounded-cornersfancy-font或者no-bullets,那么往往能夠構造一個合適的混合器。如果你找不到,這時候構造一個混合器可能并不合適。
那么在js上面,我該如何實現(xiàn)一個Mixin呢?太簡單了!我們只需要一個函數(shù)就可以了,沒錯,只需要一個返回對象的函數(shù)就可以做到這樣的效果了,加上ES7的拓展運算符,我們就可以做到一個混合器的效果:
export default StyleSheet.create({ lines: { height: px(88), backgroundColor: color.background, ...layout.border(1px, "#fff") }, });
常寫react-native的同學一定都頭疼過這樣一個問題吧,就是我們并不能像寫css樣式一樣在一行中把所有的屬性都寫完,在css中我們如果想要聲明一個四面邊框的大小,可以這樣寫:
.border { border: 10px 5px 10px 5px; }
那么在我們寫樣式的時候是不是也可以這樣寫:
export default StyleSheet.create({ lines: { height: px(88), backgroundColor: color.background, ...layout.border(10px, 5px, 10px, 5px), }, });
我們可以通過函數(shù)的不同數(shù)量的參數(shù)來模擬傳統(tǒng)css開發(fā)的簡寫屬性,很多時候我們更習慣在View上面去做樣式的運算,利用react-native樣式的覆蓋數(shù)組去不斷的覆蓋之前的樣式來達到運算的結果,這就導致View中除了需要計算你的組件要不要展示、如何展示之外,還要去計算樣式該如何寫,既然我們要做樣式和頁面的分離,那就應該做徹底一些,將樣式的計算也放在style.js中。
總結最后總結一下我們所做的:
分離樣式和頁面
提取項目級的公共屬性
歸類提取的公共樣式
通過混合器去創(chuàng)造模板樣式
我建議無論你的項目多大,代碼多少,前三步都應該是一個必備的環(huán)節(jié),可能你的項目不復雜,暫時用不到第四點,但前三條無論如何都應該盡早的去完善,這不僅僅能幫助你實現(xiàn)后續(xù)的迭代,也能在你的腦中保留出一個對于項目完整結構的印象,要知道樣式是寄生于頁面的,清楚了樣式,那么頁面如何你也多少會爛熟于心了。而相比于通過梳理js的邏輯去了解整個項目,我想通過頁面也許會更快吧,這對剛剛接手項目的新同學來說,是非常友善的。
最后的最后一般到這里,就該放上自己開源的項目地址或者安利一波作者寫的庫了,不過和上一篇一樣,這里我們只討論思路,表述想法,而具體的實踐和代碼還是要靠我們自己在項目中不斷的總結和積累~
我相信很多同學對于我提到的前三點都會很快的理解,而對于第四點可能就有些懵了,該怎么去理解這個混合器呢?我該怎么用js去實現(xiàn)一個呢?下面我就用一段代碼來舉個例子,該如何實現(xiàn)一個Mixin:
const layout = { // 這里的形參順序遵循css中的 “上、右、下、左” margin(...arg) { let margin = {}; switch (arg.length) { case 1: margin = { marginTop: arg[0], marginRight: arg[0], marginBottom: arg[0], marginLeft: arg[0], }; break; case 2: margin = { marginVertical: arg[0], marginHorizontal: arg[1], }; break; case 3: margin = { marginTop: arg[0], marginHorizontal: arg[1], marginBottom: arg[2], }; break; case 4: margin = { marginTop: arg[0], marginRight: arg[1], marginBottom: arg[2], marginLeft: arg[3], }; break; default: break; } return margin; }, };
這是一個最簡易的Mixin,你可以根據(jù)你的需求去寫更多這樣的Mixin,其實我個人覺得在項目一開始的時候是不一定需要這個的,這個存在的意義是對于復雜樣式書寫的,更多的情況下,你的項目只要做到了前三點,在樣式這一塊就已經非常的整潔、完善了,多數(shù)情況下你不需要Mixin就能組織好你的代碼。
好了,以上就是這次我想和大家聊的關于react-native中樣式的話題了,我們下次見~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/107588.html
摘要:個人感覺這與中的布局文件類似。其中的會被解析。中的標簽,由基礎庫提供。認為,我們的程序是一個狀態(tài)機。支持我們更改狀態(tài),從而引起視圖的變化。綁定事件是放在中的。事件名稱直接寫為標簽的屬性,其值則是對應的事件處理函數(shù)。 這一系列課程說了很多關于react-native的知識,都是有關于樣式,底層,環(huán)境等知識的,現(xiàn)在我們來學習一下reactjs的基礎知識。我們的代碼,我們創(chuàng)建的組件的相關知識...
摘要:跟非常相似,但是在開始嘗試你第一個之前,也需要了解兩者之間的一些差異。推薦的方式是使用提供的。能用到組件中的或者上以啟用這個組件的觸摸事件。 華翔,Web前端開發(fā)工程師著作權歸作者所有,轉載請聯(lián)系作者獲得授權。 showImg(https://segmentfault.com/img/bVUliz?w=640&h=235); React-Native已經誕生有兩年左右了,自從適配了An...
摘要:圍觀本文需自備,,以及。使用打開,并點擊,會看到模擬器以及此項目對應的內容,效果如下如果想要修改顯示內容,請打開,里面是一堆模樣的東西。接下來,我們按照教程,來展示一張電影海報,為了方便,我們直接修改。 原文鏈接:http://www.tinghaige.com/ 本著什么都要攙和的原則,一起來看看React Native是如何開發(fā)iOS APP。 圍觀本文需自備Mac OSX ,...
監(jiān)控什么 今天我們來聊聊如何監(jiān)控你的應用程序,這里的監(jiān)控說的不是讓我們去監(jiān)控用戶,而是監(jiān)控應用的健康狀態(tài),什么是健康狀態(tài)呢?對于后端的同學來說,在微服務的架構下,每個子服務是否正常工作、返回的結果是否滿足預期,這些就算是健康狀態(tài),再舉個例子,你的臺式機,對于操作系統(tǒng)來說,每個硬件是否能正常的工作、工作的穩(wěn)定性,這些都是需要關注的健康狀態(tài)。 既然我們關心健康狀態(tài),那么我們該如何衡量一個設備的健康狀態(tài)...
閱讀 3494·2021-11-24 11:17
閱讀 2281·2021-11-15 11:38
閱讀 3367·2021-10-14 09:42
閱讀 2930·2019-08-30 15:54
閱讀 2024·2019-08-28 18:09
閱讀 539·2019-08-26 11:48
閱讀 1632·2019-08-26 10:48
閱讀 2146·2019-08-26 10:45