何提升Web頁面的性能,很多開發人員從多個方面來下手如JavaScript、圖像優化、服務器配置,文件壓縮或是調整CSS。
很顯然HTML 已經達到了一個瓶頸,盡管它是開發Web 界面必備的核心語言。HTML頁面的負載也是越來越重。大多數頁面平均需要40K的空間,像一些大型網站會包含數以千計的HTML 元素,頁面Size會更大。
如何有效的降低HTML 代碼的復雜度和頁面元素的數量,本文主要解決了這個問題,從多個方面介紹了如何編寫簡練,清晰的HTML 代碼,能夠使得頁面加載更為迅速,且能在多種設備中運行良好。
在設計和開發過程中需要遵循以下原則:
HTML,CSS 和JavaScript三者的關系
HTML 是用于調整頁面結構和內容的標記語言。HTML 不能用于修飾樣式內容,也不能在頭標簽中輸入文本內容,使代碼變得冗長和復雜,相反使用CSS 來修飾布局元素和外觀比較合適。HTML元素默認的外觀是由瀏覽器默認的樣式表定義的,如在Chrome中h1標簽元素會渲染成32px的Times 粗體。
三條通用設計規則:
文檔結構方面也可以做優化,如下:
<!DOCTYPE html> <html> <head> <title>Recipes: pesto</title> </head> <body> <h1>Pesto</h1> <p>Pesto is good!</p> </body> </html>
<head> <title>My pesto recipe</title> <link rel="stylesheet" href="/css/global.css"> <link rel="stylesheet" href="css/local.css"> </head>
使用這兩種方法,瀏覽器會在解析HTML代碼之前將CSS信息準備好。因此有助于提升頁面加載性能。
在頁面底部body結束標簽之前輸入JavaScript代碼,這樣有助于提升頁面加載的速度,因為瀏覽器在解析JavaScript代碼之前將頁面加載完成,使用JavaScript會對頁面元素產生積極的影響。
<body> ... <script src="/js/global.js"> <script src="js/local.js"> </body>
使用Defer和async屬性,腳本元素具有async 屬性無法保證會按順序執行。
可在JavaScript代碼中添加Handlers。千萬別加到HTML內聯代碼中,比如下面的代碼則容易導致錯誤且不易于維護:
index.html:
<head> ... <script src="js/local.js"> </head> <body onload="init()"> ... <button onclick="handleFoo()">Foo</button> ... </body>
下面的寫法比較好:
index.html:
<head> ... </head> <body> ... <button id="foo">Foo</button> ... <script src="js/local.js"> </body>
js/local.js:
init(); var fooButton = document.querySelector('#foo'); fooButton.onclick = handleFoo();
驗證
優化網頁的一種方法就是瀏覽器可處理非法的HTML 代碼。合法的HTML代碼很容易調試,且占內存少,耗費資源少,易于解析和渲染運行起來更快。非法的HTML代碼讓實現響應式設計變得異常艱難。
當使用模板時,合法的HTML代碼顯得異常重要,經常會發生模板單獨運行良好,當與其他模塊集成時就報各種各樣的錯誤,因此一定要保證HTML代碼的質量,可采取以下措施:
代碼格式
格式一致性使得HTML代碼易于閱讀,理解,優化,調試。
語義標記
語義指意義相關的事物,HTML 可從頁面內容中看出語義:元素和屬性的命名一定程度上表達了內容的角色和功能。HTML5 引入了新的語義元素,如<header>,<footer>及<nav>。
選擇合適的元素來編寫代碼可保證代碼的易讀性:
例如:
<div>Name: <input type="text" id="name"></div>
換種寫法會更好:
1: <div> 2: <label for="name">Name:</label><input type="text" id="name"> 3: </div>
布局
要提高HTML代碼的性能,要遵循HTML 代碼以實現功能和為目標,而不是樣式。
CSS
雖然本文講解的是如何優化HTML,下面介紹了一些使用css的基本技能:
以上就是本文介紹的優化HTML代碼的技巧,一個高質量高性能的網站,往往取決于對細節的處理,因此我們在日常開發中,能夠考慮到用戶體驗,后期維護等方面,則會產生更高效的開發。
者:HXGNMSL來源:CSDN原文:https://blog.csdn.net/HXGNMSL/article/details/89076476
Javascript的歷史來源
94年網景公司 研發出世界上第一款瀏覽器。
95年 sun公司 java語言誕生
網景公司和sun合作。
Javascript ===> javascript
JavaScript和ECMAScript的關系
簡單來說ECMAScript不是一門語言,而是一個標準。符合這個標準的比較常見的有:JavaScript、Action Script(Flash中用的語言)
JavaScript的基本結構:
JavaScript的語法:
JavaScript的基礎語法
變量的聲明及使用
數據類型
運算符
邏輯控制語句
注釋
語法規則
變量的聲明語法:
var變量名;
例如:
Var num;
然后進行賦值:num = 10;也可以聲明時直接賦值:
Var num =10;
在JavaScript中,提供了常用的基本數據類型:
undefined 未定義;
null 空;
string 字符串類型;
boolean 布爾類型;
number 數值類型;
運算符:
算數運算符:+、-、*、/、%、++、–;
比較運算符:>、<、> =、< =、==、!=;
邏輯運算符:&&、||、!;
賦值運算符:=;
邏輯控制語句:
JavaScript的邏輯控制語句也分為兩類:條件結構和循環機構。
條件結構
條件機構分為if結構和switch結構:
If…else
Switch
循環結構
JavaScript的循環結構的執行順序與Java類似,主要包括以下幾種結構:
for循環
while循環
do…while循環
for…inx循環
示例:
for(var i=0;i<10;i++){
Document.write(“*”);
}
輸出結果:**********
循環中斷:
用于循環中斷的語句有以下兩種:
break.
continue.
與Java用法一樣,break是跳出循環,continue是跳入下一次循環。
函數
函數有兩種:一種是系統函數,一種是自定義函數。
常用的系統函數包括:
parseInt():轉換為整數。
parseFloat():轉換為浮點型。
isNaN():判斷非數字。
Eval():計算表達式值。
自定義函數:
自定義函數的語法
function 函數名(參數1,參數2,…){
…//語句
Return 返回值;//可選
}
函數的調用:
函數的調用方式有以下兩種
事件名=函數名(傳遞的實參值),例如:
“函數名()”
直接使用函數名(傳遞的實參值),例如:
var recult = add(2,3);
匿名函數
匿名函數的語法
var sumFun=function(num1,num2){
…
return(nun1,num2);
} ;
在語法中:
var sunFun=function(num1,num2)表示聲明一個變量等于某個函數體。
{…};是把整個函數體放在變量的后面,并把末尾添加一個分號。
匿名函數的調用:
由于匿名函數定義的整個語句,可以像賦值一樣賦給一個變量進行保存,所以可以使用如下方式調用語法中的匿名函數:
var sum=sumFun(2,3)
BOM概述
使用BOM可以移動窗口,改變狀態欄中的文本,執行其他與頁面內容不直接相關的動作。它包含的對象主要有以下幾種;
Window對象
Window對象是指整個窗口對象,可以通過操作Window對象的屬性和方法控制窗口,例如,打開或關閉一個窗口。
History對象
瀏覽器訪問過的歷史頁面對應History對象,通過History對象的屬性和方法實現瀏覽器的前進或后退的功能。
Location對象
瀏覽器的地址欄對應Location對象,通過Location對象的屬性和方法控制頁面跳轉。
Document對象
瀏覽器內的網頁內容對應Document對象,通過Document對象的屬性和方法,控制頁面元素。
Window常用的屬性有:
history:有關客戶訪問過的URL的信息。
location:有關當前URL的信息。
Screen: 有關客戶端的屏幕和顯示性能的信息。
Window對象常用的方法:
prompt():顯示可提示用戶輸入的對話框。
alert():顯示帶有一段消息和一個人“確認”按鈕的警告框。
confirm():顯示帶有一段消息以及“確認”按鈕“取消”按鈕的對話框。
close():關閉瀏覽器窗口。
open():打開一個新的瀏覽器窗口,加載給定URL所指定的文檔。
setTimeout():用于在指定(以毫秒計)后調用函數或計算表達式。
setTneerval():按照指定的周期 (以毫秒計)數來調用函數或計算表達式。
Window對象常用窗口特征屬性
height、width:窗口文檔顯示區的高度、寬度,以像素計。
left、top:窗口的x坐標y坐標,以像素計。
toolbar:yes|no|1|0:是否顯示瀏覽器的工具欄,默認是yes。
scrollbars =yes|no|1|0:是否顯示滾動條,默認是yes。
locationyes|no|1|0:是否顯示地址欄,默認是yes。
status|no|1|0:是否添加地址欄,默認是yes。
menubar|no|1|0:是否顯示菜單欄,默認是yes。
resizable|no|1|0:窗口是否可調節尺寸,默認是yes。
Window對象的常用事件:
onload:一個頁面或一副圖像完成加載。
onmouseover:鼠標指針移到某元素之上。
onclick:單擊某個對象。
onkeydown:某個鍵盤按鍵被按下。
onchange:域的內容被改變。
History對象的方法:
back():加載History對象列表中的上一個URL。
forward():加載History對象列表中的下一個URL。
go():加載History對象列表中的某個具體URL。
Location對象的屬性:
host:設置或返回主機名和當前URL的端口號。
hostname:設置或返回當前URL的主機名。
href:設置或返回完整的URL。
Location對象的方法:
reload():重新加載當前文檔。
replace():用新的文檔替換當前文檔。
Document對象常用的屬性:
referrer:返回載入當前文檔的URL。
URL:返回當前文檔的URL。
Document對象的常用方法:
getElementById():返回對擁有指定id的第一個對象的引用。
getElementsByName():返回帶有指定名稱的對象的集合。
getElementsByTagName():返回帶有指定標簽名的對象的集合。
write():向文檔寫文本、HTML表達式代碼。
內置對象
系統的內置對象有Date對象、Array對象、String對象和Math對象等。
Date:用于操作日期和時間。
Array:用于在單獨的變量名中儲存一系列的值。
String:用于支持對字符串的處理。
Math:用于執行數學任務,包含了若干數字常量和函數。
Date對象:
1:創建日期對象
Date對象包含日期和時間兩個信息,創建日期對象的基本語法有兩種:
創建日期的基本語法1: var 日期實例化=new Date(參數);
創建日期的基本語法2: var 日期實例化=new Date();
Date對象的常用方法:
getDate():從Date對象返回一個月中的某一天,其值介于1到31之間。
getDay():從Date對象返回星期中的某一天,其值介于0到6之間。
getHours():返回Date對象的小時,其值介于0到23之間。
getMinutes():返回Date對象的分鐘,其值介于0到59之間。
getSeconds():返回Date對象的秒數,其值介于0到59之間。
getMonth():返回Date對象的月份,其值介于0到11之間。
getFullYear():返回Date對象的年份,其值為4位數。
getTime():返回自某一時刻(2010年1月1日)以來的毫秒數。
DOM概述
什么是DOM
DOM是文檔對象的縮寫,和語言無關。它提供了訪問、動態修改結構文檔的接口,W3C制定了DOM規范,主流瀏覽器都支持。
使用Core DOM操作節點
訪問節點:
使用getElement系列方法訪問指定節點。
getElementById():返回對擁有指定id的第一個對象的引用。
getElementsByName():返回帶有指定名稱的對象的集合。
getElementsByTagName():返回帶有指定標簽名的對象的集合。
使用層次關系訪問節點。
parenNode:返回節點的父節點。
firstChild:返回節點的首個節點。文本和屬性節點沒有父節點,會返回一個空數組,對于元素節點,若是沒有子節點會返回null。
lastChild:返回節點的最后一個子節點,返回值同firstChild。
操作節點屬性值
CoreDOM的標準方法包括以下兩種:
getAttribute(“屬性名”):獲取屬性值。
getAttribute(“屬性名”,“屬性值”):設置屬性值
創建和增加節點:
創建節點
createElement(tagName):按照給定的標簽名稱創建一個新的元素節點
appendChild(nodeName):向以存在節點列表的末尾添加新的節點。
inserBefore(newNode,oldNode):向指定的節點之前插入一個新的子節點。
cloneNode(deep):復制某個指定的節點。
刪除和替換節點
removeChild(node):刪除指定的節點。
replaceChild(newNode,oldNode):用其他的節點替換指定的節點。
Table對象的屬性和方法
屬性:
rows[]:返回包含表格中所有行的一個數組。
rows[]用于返回表格中所有行的一個數組。
方法:
inserRow():在表格中插入一個新行。
deleteRow():從表格中刪除一行。
數組
數組是具有相同數據類型的一個或多個值得集合
創建數組的語法:
var 數組名稱=new Array(size);
數組的賦值的兩種方式:
先聲明在賦值
var province = new Array(4);
province[0]=“河北省”;
province[1]=“河南省”;
索引也可以使用標識(字符串),例如:
var province=new Array(4);
province[‘河北省’]=“河北省”;
province[‘河南省’]=“河南省”;
聲明時同時初始化
var province=new Array(“河北省”,“河南省”,“湖北省”,“廣東省”);
Array對象的常用屬性和方法:
屬性:
length:設置或返回數組中元素的數目。
方法:
join():把數組的所有元素放入一個字符串,通過一個分隔符進行分割。
sort():對數組的元素進行排序。
家好,我是皮湯。最近業務調整,組內開啟了前端工程化方面的基建,我主要負責 CSS 技術選型這一塊,針對目前業界主流的幾套方案進行了比較完善的調研與比較,分享給大家。
目前整個 CSS 工具鏈、工程化領域的主要方案如下:
而我們技術選型的標準如下:
- 開發速度快
- 開發體驗友好
- 調試體驗友好
- 可維護性友好
- 擴展性友好
- 可協作性友好
- 體積小
- 有最佳實踐指導
目前主要需要對比的三套方案:
- Less/Sass + PostCSS 的純 CSS c側方案
- styled-components / emotion 的純 CSS-in-JS 側方案
- TailwindCSS 的以寫輔助類為主的 HTML 側方案
## 純 CSS 側方案
### 介紹與優點
> 維護狀態:一般
> Star 數:16.7K
> 支持框架:無框架限制
> 項目地址:https://github.com/less/less.js
Less/Sass + PostCSS 這種方案在目前主流的組件庫和企業級項目中使用很廣,如 ant-design 等
它們的主要作用如下:
- 為 CSS 添加了類似 JS 的特性,你也可以使用變量、mixin,寫判斷等
- 引入了模塊化的概念,可以在一個 less 文件中導入另外一個 less 文件進行使用
- 兼容標準,可以快速使用 CSS 新特性,兼容瀏覽器 CSS 差異等
這類工具能夠與主流的工程化工具一起使用,如 Webpack,提供對應的 loader 如 sass-loader,然后就可以在 React/Vue 項目中建 `.scss` 文件,寫 sass 語法,并導入到 React 組件中生效。
比如我寫一個組件在響應式各個斷點下的展示情況的 sass 代碼:
```
.component {
width: 300px;
@media (min-width: 768px) {
width: 600px;
@media (min-resolution: 192dpi) {
background-image: url(/img/retina2x.png);
}
}
@media (min-width: 1280px) {
width: 800px;
}
}
```
或導入一些用于標準化瀏覽器差異的代碼:
```
@import "normalize.css";
// component 相關的其他代碼
```
### 不足
這類方案的一個主要問題就是,只是對 CSS 本身進行了增強,但是在幫助開發者如何寫更好的 CSS、更高效、可維護的 CSS 方面并沒有提供任何建議。
- 你依然需要自己定義 CSS 類、id,并且思考如何去用這些類、id 進行組合去描述 HTML 的樣式
- 你依然可能會寫很多冗余的 Less/Sass 代碼,然后造成項目的負擔,在可維護性方面也有巨大問題
### 優化
- 可以引入 CSS 設計規范:BEM 規范,來輔助用戶在整個網頁的 HTML 骨架以及對應的類上進行設計
- 可以引入 CSS Modules,將 CSS 文件進行 “作用域” 限制,確保在之后維護時,修改一個內容不會引起全局中其他樣式的效果
#### BEM 規范
B (Block)、E(Element)、M(Modifier),具體就是通過塊、元素、行為來定義所有的可視化功能。
拿設計一個 Button 為例:
```
/* Block */
.btn {}
/* 依賴于 Block 的 Element */
.btn__price {}
/* 修改 Block 風格的 Modifier */
.btn--orange {}
.btn--big {}
```
遵循上述規范的一個真實的 Button:
```
<a class="btn btn--big btn--orange" href="#">
<span class="btn__price"></span>
<span class="btn__text">BIG BUTTON</span>
</a>
```
可以獲得如下的效果:
#### CSS Modules
CSS Modules 主要為 CSS 添加局部作用域和模塊依賴,使得 CSS 也能具有組件化。
一個例子如下:
```
import React from 'react';
import style from './App.css';
export default () => {
return (
<h1 className={style.title}>
Hello World
</h1>
);
};
```
```
.title {
composes: className;
color: red;
}
```
上述經過編譯會變成如下 hash 字符串:
```
<h1 class="_3zyde4l1yATCOkgn-DBWEL">
Hello World
</h1>
```
```
._3zyde4l1yATCOkgn-DBWEL {
color: red;
}
```
CSS Modules 可以與普通 CSS、Less、Sass 等結合使用。
## 純 JS 側方案
### 介紹與優點
> 維護狀態:一般
> Star 數:35.2K
> 支持框架:React ,通過社區支持 Vue 等框架
> 項目地址:https://github.com/styled-components/styled-components
使用 JS 的模板字符串函數,在 JS 里面寫 CSS 代碼,這帶來了兩個認知的改變:
- 不是在根據 HTML,然后去寫 CSS,而是站在組件設計的角度,為組件寫 CSS,然后應用組件的組合思想搭建大應用
- 自動提供類似 CSS Modules 的體驗,不用擔心樣式的全局污染問題
同時帶來了很多 JS 側才有的各種功能特性,可以讓開發者用開發 JS 的方式開發 CSS,如編輯器自動補全、Lint、編譯壓縮等。
比如我寫一個按鈕:
```
const Button = styled.button`
/* Adapt the colors based on primary prop */
background: ${props => props.primary ? "palevioletred" : "white"};
color: ${props => props.primary ? "white" : "palevioletred"};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
render(
<div>
<Button>Normal</Button>
<Button primary>Primary</Button>
</div>
);
```
可以獲得如下效果:
還可以擴展樣式:
```
// The Button from the last section without the interpolations
const Button = styled.button`
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
// A new component based on Button, but with some override styles
const TomatoButton = styled(Button)`
color: tomato;
border-color: tomato;
`;
render(
<div>
<Button>Normal Button</Button>
<TomatoButton>Tomato Button</TomatoButton>
</div>
);
```
可以獲得如下效果:
### 不足
雖然這類方案提供了在 JS 中寫 CSS,充分利用 JS 的插值、組合等特性,然后應用 React 組件等組合思想,將組件與 CSS 進行細粒度綁定,讓 CSS 跟隨著組件一同進行組件化開發,同時提供和組件類似的模塊化特性,相比 Less/Sass 這一套,可以復用 JS 社區的最佳實踐等。
但是它仍然有一些不足:
- 仍然是是對 CSS 增強,提供非常大的靈活性,開發者仍然需要考慮如何去組織自己的 CSS
- 沒有給出一套 “有觀點” 的最佳實踐做法
- 在上層也缺乏基于 styled-components 進行復用的物料庫可進行參考設計和使用,導致在初始化使用時開發速度較低
- 在 JS 中寫 CSS,勢必帶來一些本屬于 JS 的限制,如 TS 下,需要對 Styled 的組件進行類型注釋
- 官方維護的內容只兼容 React 框架,Vue 和其他框架都由社區提供支持
整體來說不太符合團隊協作使用,需要人為總結最佳實踐和規范等。
### 優化
- 尋求一套寫 CSS 的最佳實踐和團隊協作規范
- 能夠擁有大量的物料庫或輔助類等,提高開發效率,快速完成應用開發
## 偏向 HTML 側方案
### 介紹與優點
> 維護狀態:積極
> Star 數:48.9K
> 支持框架:React、Vue、Svelte 等主流框架
> 項目地址:https://github.com/tailwindlabs/tailwindcss
典型的是 TailwindCSS,一個輔助類優先的 CSS 框架,提供如 `flex` 、`pt-4` 、`text-center` 、`rotate-90` 這樣實用的類名,然后基于這些底層的輔助類向上組合構建任何網站,而且只需要專注于為 HTML 設置類名即可。
一個比較形象的例子可以參考如下代碼:
```
<button class="btn btn--secondary">Decline</button>
<button class="btn btn--primary">Accept</button>
```
上述代碼應用 BEM 風格的類名設計,然后設計兩個按鈕,而這兩個類名類似主流組件庫里面的 Button 的不同狀態的設計,而這兩個類又是由更加基礎的 TailwindCSS 輔助類組成:
```
.btn {
@apply text-base font-medium rounded-lg p-3;
}
.btn--primary {
@apply bg-rose-500 text-white;
}
.btn--secondary {
@apply bg-gray-100 text-black;
}
```
上面的輔助類包含以下幾類:
- 設置文本相關: `text-base` 、`font-medium` 、`text-white` 、`text-black`
- 設置背景相關的:`bg-rose-500` 、`bg-gray-100`
- 設置間距相關的:`p-3`
- 設置邊角相關的:`rounded-lg`
通過 Tailwind 提供的 `@apply` 方法來對這些輔助類進行組合構建更上層的樣式類。
上述的最終效果展示如下:
可以看到 TailwindCSS 將我們開發網站的過程抽象成為使用 Figma 等設計軟件設計界面的過程,同時提供了一套用于設計的規范,相當于內置最佳實踐,如顏色、陰影、字體相關的內容,一個很形象的圖片可以說明這一點:
TailwindCSS 為我們規劃了一個元素可以設置的屬性,并且為每個屬性給定了一組可以設置的值,這些屬性+屬性值組合成一個有機的設計系統,非常便于團隊協作與共識,讓我們開發網站就像做設計一樣簡單、快速,但是整體風格又能保持一致。
TailwindCSS 同時也能與主流組件庫如 React、Vue、Svelte 結合,融入基于組件的 CSS 設計思想,但又只需要修改 HTML 上的類名,如我們設計一個食譜組件:
```
// Recipes.js
import Nav from './Nav.js'
import NavItem from './NavItem.js'
import List from './List.js'
import ListItem from './ListItem.js'
export default function Recipes({ recipes }) {
return (
<div className="divide-y divide-gray-100">
<Nav>
<NavItem href="/featured" isActive>Featured</NavItem>
<NavItem href="/popular">Popular</NavItem>
<NavItem href="/recent">Recent</NavItem>
</Nav>
<List>
{recipes.map((recipe) => (
<ListItem key={recipe.id} recipe={recipe} />
))}
</List>
</div>
)
}
// Nav.js
export default function Nav({ children }) {
return (
<nav className="p-4">
<ul className="flex space-x-2">
{children}
</ul>
</nav>
)
}
// NavItem.js
export default function NavItem({ href, isActive, children }) {
return (
<li>
<a
href={href}
className={`block px-4 py-2 rounded-md ${isActive ? 'bg-amber-100 text-amber-700' : ''}`}
>
{children}
</a>
</li>
)
}
// List.js
export default function List({ children }) {
return (
<ul className="divide-y divide-gray-100">
{children}
</ul>
)
}
//ListItem.js
export default function ListItem({ recipe }) {
return (
<article className="p-4 flex space-x-4">
<img src={recipe.image} alt="" className="flex-none w-18 h-18 rounded-lg object-cover bg-gray-100" width="144" height="144" />
<div className="min-w-0 relative flex-auto sm:pr-20 lg:pr-0 xl:pr-20">
<h2 className="text-lg font-semibold text-black mb-0.5">
{recipe.title}
</h2>
<dl className="flex flex-wrap text-sm font-medium whitespace-pre">
<div>
<dt className="sr-only">Time</dt>
<dd>
<abbr title={`${recipe.time} minutes`}>{recipe.time}m</abbr>
</dd>
</div>
<div>
<dt className="sr-only">Difficulty</dt>
<dd> · {recipe.difficulty}</dd>
</div>
<div>
<dt className="sr-only">Servings</dt>
<dd> · {recipe.servings} servings</dd>
</div>
<div className="flex-none w-full mt-0.5 font-normal">
<dt className="inline">By</dt>{' '}
<dd className="inline text-black">{recipe.author}</dd>
</div>
<div class="absolute top-0 right-0 rounded-full bg-amber-50 text-amber-900 px-2 py-0.5 hidden sm:flex lg:hidden xl:flex items-center space-x-1">
<dt className="text-amber-500">
<span className="sr-only">Rating</span>
<svg width="16" height="20" fill="currentColor">
<path d="M7.05 3.691c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.372 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.539 1.118l-2.8-2.034a1 1 0 00-1.176 0l-2.8 2.034c-.783.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.363-1.118L.98 9.483c-.784-.57-.381-1.81.587-1.81H5.03a1 1 0 00.95-.69L7.05 3.69z" />
</svg>
</dt>
<dd>{recipe.rating}</dd>
</div>
</dl>
</div>
</article>
)
}
```
上述食譜的效果如下:
可以看到我們無需寫一行 CSS,而是在 HTML 里面應用各種輔助類,結合 React 的組件化設計,既可以輕松完成一個非常現代化且好看的食譜組件。
除了上面的特性,TailwindCSS 在響應式、新特性支持、Dark Mode、自定義配置、自定義新的輔助類、IDE 方面也提供非常優秀的支持,除此之外還有基于 TailwindCSS 構建的物料庫 Tailwind UI ,提供各種各樣成熟、好看、可用于生產的物料庫:

因為需要自定的 CSS 不多,而需要自定義的 CSS 可以定義為可復用的輔助類,所以在可維護性方面也是極好的。
### 不足
- 因為要引入一個額外的運行時,TailwindCSS 輔助類到 CSS 的編譯過程,而隨著組件越來越多,需要編譯的工作量也會變大,所以速度會有影響
- 過于底層,相當于給了用于設計的最基礎的指標,但是如果我們想要快速設計網站,那么可能還需要一致的、更加上層的組件庫
- 相當于引入了一套框架,具有一定的學習成本和使用成本
### 優化
- Tailwind 2.0 支持 [JIT](https://blog.tailwindcss.com/tailwindcss-2-1 "JIT"),可以大大提升編譯速度,可以考慮引入
- 基于 TailwindCSS,設計一套符合自身風格的上層組件庫、物料庫,便于更加快速開發
- 提前探索、學習和總結一套教程與開發最佳實踐
- 探索 styled-components 等結合 TailwindCSS 的開發方式
## 參考鏈接
- [CSS 工程化發展歷程](https://bytedance.feishu.cn/docs/doccnTRF0OZtJMgKuo3y0hIDMbc# "CSS 工程化發展歷程")
以上便是本次分享的全部內容,希望對你有所幫助^_^
喜歡的話別忘了 分享、點贊、收藏 三連哦~
歡迎關注公眾號 程序員巴士,來自字節、蝦皮、招銀的三端兄弟,分享編程經驗、技術干貨與職業規劃,助你少走彎路進大廠。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。