在前端開發(fā)中一直有個(gè)原則蒲列,叫做"關(guān)注點(diǎn)分離",意思就是各種技術(shù)只負(fù)責(zé)自己的領(lǐng)域晴氨,不要混合在一起茄茁,形成耦合魂贬,這種原則比較直觀的體現(xiàn)就是不要寫"行內(nèi)樣式"(inline style)和"行內(nèi)腳本"(inline script),HTML裙顽、CSS随橘、JavaScript各干各的事,避免混用(此處參考CSS in JS 簡(jiǎn)介)
現(xiàn)在前端在進(jìn)行開發(fā)時(shí)锦庸,基本都被各種框架覆蓋,新起一個(gè)項(xiàng)目蒲祈,第一步都是技術(shù)選型甘萧。看看是用 React梆掸、還是用 Vue扬卷,然后再配套的去選擇相關(guān)技術(shù)棧,以及相應(yīng)的框架酸钦。這是技術(shù)的進(jìn)度怪得,讓開發(fā)人員能比較關(guān)注業(yè)務(wù)邏輯的展開,但另一方面也可以認(rèn)為這是一種枷鎖。徒恋。蚕断。
由于框架的使用,使我們之前的關(guān)注點(diǎn)分離變的策略入挣,現(xiàn)在其實(shí)都是在 js 中進(jìn)行亿乳。HTML 以 虛擬DOM 的形式存在其中,css 通常是以 import 的形式載入径筏,最終通過(guò) webpack 之類的工具葛假,再導(dǎo)出成一個(gè)獨(dú)立的樣式文件。
相比 HTML滋恬,框架對(duì) CSS 都沒進(jìn)行什么特殊處理聊训,也沒有形成類似 JSX 的解決方案,不過(guò)這其中倒是有一個(gè)比較有意思的解決方案:css-in-js(不過(guò)在 js 中寫 css恢氯,怎么都感覺有些別扭)带斑。
另外 css 本身編程能力薄弱,社區(qū)也形成各種方案來(lái)提升 css 編程能力酿雪。相比其他方案遏暴,我感覺 Postcss 更為優(yōu)雅,所以這里特別介紹下
目前是基于 postcss 7.0.31 版本
基本概念
- Postcss是一個(gè)用 js 插件轉(zhuǎn)換成 css 的工具
- Postcss 不是預(yù)處理器
預(yù)處理器是指對(duì) css 能力增強(qiáng)的功能指黎,添加一些一些本身不是css的功能(比如嵌套朋凉、變量),通過(guò)處理后能轉(zhuǎn)成普通的CSS醋安,
- Postcss 不是后處理器
通過(guò)一些規(guī)則把已有的css進(jìn)行完善杂彭,比如添加瀏覽器前綴
- Postcss 是作為一個(gè)平臺(tái)的存在,利用 Postcss 提供的插件可以組合各種不同模塊吓揪,來(lái)構(gòu)建更為復(fù)雜的功能
Demo
此處沒有使用vue或react的腳手架亲怠,為了演示完整功能,構(gòu)建了一個(gè)基于Vue的開發(fā)環(huán)境柠辞,并演示加載樣式和提取
- 任意目錄 npm init -y
使用這種方式团秽,項(xiàng)目的名詞一定不要和某些庫(kù)的名詞沖突,比如叫webpack叭首,postcss习勤,如果叫這個(gè)名詞安裝相關(guān)庫(kù)時(shí)就會(huì)報(bào)ENOSELF的錯(cuò)誤
- 安裝 相關(guān)依賴
npm i --save-dev webpack webpack-cli webpack-dev-server html-webpack-plugin postcss postcss-loader mini-css-extract-plugin css-loader style-loader @babel/cli @babel/core @babel/preset-env vue-loader vue-template-compiler
npm i --save vue
* css-loader 是可以在頁(yè)面中使用 import 引入 css 的能力
* style-loader 是把 css 代碼生成 style 標(biāo)簽,放到 head 標(biāo)簽中
* mini-css-extract-plugin 提取css用的插件
其他包不在本文討論范圍焙格,故不介紹
- 新建兩個(gè)文件夾
src
图毕、dist
,以及babel.config.js
眷唉、webpack.config.js
和其他相關(guān)文件
/// babel.config.js
const presets = [["@babel/env"]];
module.exports = {
presets
}
...
/// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
module.exports = {
entry: './src/index.js',
resolve: {
extensions: ['.js', '.vue']
},
output: {
filename: '[name].js',
publicPath: '/'
},
mode: 'development',
module: {
rules: [
{test: /\.js$/, use: 'babel-loader', exclude: /node_modules/},
{test: /\.vue$/, use: 'vue-loader', exclude: /node_modules/},
{test: /\.css/, use: ['style-loader', 'css-loader']}
]
},
devServer: {
port: '8111'
},
plugins: [
new HtmlWebpackPlugin({
template: './src/tpl/index.html'
}),
new VueLoaderPlugin()
]
}
...
/// 假定有個(gè) app.vue 按如上設(shè)置
import '../style/app.css';
這時(shí)就可以通過(guò) import
方式把樣式文件導(dǎo)入到頁(yè)面中予颤,因?yàn)榇藭r(shí)用的是 style-loader
囤官,樣式會(huì)寫入到 <head>
下的 <style>
標(biāo)簽中
- 如不喜歡那種在把樣式一股腦掉到
<head>
的方式,可使用 mini-css-extract-plugin 蛤虐,這會(huì)把相關(guān)樣式拆分成一個(gè)個(gè)獨(dú)立的文件
/// webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
...
{test: /\.css/, use: [MiniCssExtractPlugin.loader, 'css-loader']} // 替換 style-loader
...
plugins: [
...
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
]
- 如
import
多個(gè)文件党饮,按目前的設(shè)置,會(huì)合并和一個(gè)樣式文件導(dǎo)出笆焰,不過(guò)這些文件中的內(nèi)容劫谅,只是簡(jiǎn)單的合并在一起,而且也沒編程思想在其中嚷掠,完全依賴樣式編寫人員控制每個(gè)樣式文件的內(nèi)容
/// app.css
.info {
font-size: 24px;
}
...
/// color.css
.info {
color: red;
}
...
/// app.vue
import '../style/app.css';
import '../style/color.css';
...
/// 合并出的樣式文件如下
.info {
font-size: 24px;
}
.info {
color: red;
}
編程化
通過(guò) .pcss 引入樣式文件
.pcss
是 Postcss 的專用格式文件
- 安裝 postcss-import捏检,使在
.pcss
文件可以使用 @import 引入樣式文件
npm i --save-dev postcss-import
需要先添加一個(gè)對(duì) Postcss 的運(yùn)行配置文件,可以叫 .postcssrc.js
或 postcss.config.js
// 暫時(shí)沒有其他配置不皆,可以把留空
module.exports = {
plugins: []
}
postcss.config.js
除了 plugins
還具有如下參數(shù):
- syntax: 提供語(yǔ)法分析器和字符串化器的對(duì)象
- parser: 特殊的語(yǔ)法解析器(例如贯城,SCSS)
- stringifier: 特殊語(yǔ)法輸出生成器(例如Midas)
- map: 對(duì)map文件的設(shè)置
- from: 輸入文件名
- to: 輸出文件名
不過(guò)常用的就是 plugins
(定義使用的插件)
/// 在webpack.config.js中做如下修改
{test: /\.pcss$/, use: [
MiniCssExtractPlugin.loader,
"css-loader",
"postcss-loader"
]},
...
/// mian.pcss
@import './app.css';
@import './color.css';
...
/// app.vue 引入 main.pcss
import './main.pcss';
PostCss 的編程能力,是通過(guò)各種插件實(shí)現(xiàn)的霹娄,可以自己編寫能犯,或者直接使用社區(qū)現(xiàn)有插件,插件在 Postcss 的配置文件中設(shè)置使用參數(shù)
autoprefixer
這應(yīng)該是postcss中使用最為廣泛的插件了犬耻,自動(dòng)識(shí)別設(shè)定的瀏覽器兼容范圍踩晶,添加瀏覽器樣式前綴
npm i --save-dev autoprefixer
/// postcss.config.js
let postcssConfig = {};
postcssConfig.autoprefixer = {
browsers: ['> 1%', 'ff 3']
}
module.exports = {
plugins: postcssConfig
}
- 修改main.pcss內(nèi)容如下
b {
border-radius:5px;
}
編譯運(yùn)行后結(jié)果為
b {
-moz-border-radius:5px;
border-radius:5px;
}
autoprefixer 的參數(shù),使用默認(rèn)配置即可枕磁。這里只說(shuō) browsers 參數(shù)的設(shè)定渡蜻,因?yàn)檫@關(guān)系到最終添加前綴的內(nèi)容。
browsers 是利用 browserslist 功能來(lái)決定是否需要添加某些瀏覽器前綴计济,在browserslist的文檔里我們可以找到詳細(xì)設(shè)定茸苇,可以設(shè)定針對(duì)瀏覽器、國(guó)家沦寂、指定平臺(tái)学密、年份做設(shè)置
> 5%
cover 99.5%
> 5% in US
node 10 and node 10.4
since 2015
ie 6-8
not ie <= 8
下面列舉下在項(xiàng)目中最有可能碰到的瀏覽器
- Android: Android webview瀏覽器
- iOS: ios的Safari瀏覽器
- Chrome: 谷歌瀏覽器
- ChromeAndroid: 谷歌瀏覽器安卓版
- Edge: 微軟的Edge瀏覽器
- ie: ie瀏覽器
- Safari: Safari桌面瀏覽器
- ff: firefox瀏覽器
- and_ff: firefox安卓瀏覽器
- and_qq: QQ瀏覽器安卓版
- and_uc: UC瀏覽器安卓版
browsers
接收的是一個(gè)數(shù)組,所以可以像例子中那樣分開設(shè)置传藏,下面的話的意思就是為了適配 安卓2.3腻暮,ios3.2,Safari3.1毯侦,IE10 瀏覽器要添加相關(guān)前綴
'> 0%','Android 2.3','iOS 3.2','Safari 3.1','IE 10'
> 0%
是指當(dāng)你不想像上面設(shè)置那么繁瑣的指定瀏覽器時(shí)西壮,可以直接指定個(gè)大概,就是我要支持市面上多少多少比例的瀏覽器叫惊,這個(gè)數(shù)字前面可以添加普通的運(yùn)算符 >
塘装、>=
审丘、<
、<=
前綴修飾符 not 表示不在某個(gè)范圍中砚哗,還可以使用 cover
extends
或 since
進(jìn)行更細(xì)化的設(shè)置,包括道指定從哪年開始的什么版本蔗坯。
圓角功能是 ff4 才加的功能康震,我們指定適配某個(gè)瀏覽器版本,這時(shí)就會(huì)發(fā)現(xiàn)運(yùn)行后的樣式一樣會(huì)有ff的私有前綴宾濒,所以一般我們結(jié)合瀏覽器覆蓋范圍腿短,再加上對(duì)特定瀏覽器的排除就能完成相關(guān)設(shè)置
/// 如此設(shè)定后,生成的樣式就不會(huì)有針對(duì) 火狐瀏覽器 的前綴
browsers: ['> 1%', 'ff > 4']
有一點(diǎn)需要注意的绘梦,設(shè)置范圍時(shí)需要指定范圍橘忱,不能直接設(shè)置ff或者not ff,這時(shí)編譯會(huì)報(bào)錯(cuò)卸奉,你需要明確指明版本才可以
在 package.json 中設(shè)置 browserslist
由于還會(huì)有其他插件(比如 babel )需要針對(duì)瀏覽器設(shè)置兼容情況钝诚,所以針對(duì)瀏覽器的范圍設(shè)定,一般會(huì)建議加上 package.json
中榄棵。
在其中凝颇,設(shè)置 "browserslist": ["> 1%", "ff > 4"]
(package.json 中設(shè)定的優(yōu)先級(jí)低于插件的設(shè)置)
postcss-preset-env
這個(gè)插件允許開發(fā)人員在當(dāng)前項(xiàng)目中使用 css 將來(lái)版本可能會(huì)加入的新特性,這個(gè)就非常類似于寫 ES6 的代碼疹鳄,但是使用 babel 轉(zhuǎn)成 ES5 的代碼拧略。
這個(gè)插件中包含了autoprefixer
另外一個(gè)類似的插件,postcss-cssnext 已經(jīng)不再維護(hù)
npm i --save-dev postcss-preset-env
// 新增
const postcssPresetEnv = require('postcss-preset-env');
module.exports = {
plugins: [
postcssPresetEnv({
stage: 2
// browsers: 'last 2 versions' // 這個(gè)插件包含 autoprefixer 的功能瘪弓,可以在配置中進(jìn)行瀏覽器的相關(guān)設(shè)定
})
]
}
插件參數(shù)說(shuō)明
下面根據(jù)官方的文檔介紹相關(guān)設(shè)置參數(shù):
-
stage: 根據(jù)現(xiàn)行web標(biāo)準(zhǔn)的進(jìn)程(主要就是 w3c 組織認(rèn)定的標(biāo)準(zhǔn)垫蛆,所以這個(gè)插件中具備的功能都是未來(lái)很有可能直接加到 css 標(biāo)準(zhǔn)中的內(nèi)容)來(lái)決定某些 css 功能需不需要通過(guò)墊片的方式添加,可以設(shè)置 0~4 的任意數(shù)字杠茬,如果沒有設(shè)置這個(gè)值月褥,這個(gè)值默認(rèn)為 2
- 0: 這個(gè)階段處在
非官方草案或編輯草案階段
,很有可能會(huì)被刪除 - 1: 這個(gè)階段處于
實(shí)驗(yàn)階段
瓢喉,有可能會(huì)被設(shè)置為標(biāo)準(zhǔn) - 2: 這個(gè)階段處于
待定階段
宁赤,這也是插件默認(rèn)的數(shù)值,處于這個(gè)階段的功能栓票,基本可以認(rèn)為會(huì)被加到未來(lái)的標(biāo)準(zhǔn)中 - 3: 這個(gè)階段處于
穩(wěn)定階段
决左,基本上已經(jīng)有瀏覽器廠商實(shí)現(xiàn)了,可以直接使用 - 4: 這個(gè)階段處于
標(biāo)準(zhǔn)階段
- 0: 這個(gè)階段處在
features: 針對(duì)特定css功能進(jìn)行單獨(dú)設(shè)置走贪,比如設(shè)置了 stage 為 3佛猛,可以通過(guò)這個(gè)參數(shù)來(lái)特定使用還處于 stage為 2 的功能
postcssPresetEnv({
/* 使用stage為3的標(biāo)準(zhǔn),同時(shí)允許嵌套規(guī)則(嵌套是stage 0的標(biāo)準(zhǔn)) */
stage: 3,
features: {
'nesting-rules': true
}
})
browsers: 參加上面browserslist的介紹坠狡,就是設(shè)置瀏覽器的支持情況(不建議使用继找,直接在package.json 中設(shè)置)
insertBefore / insertAfter: 允許你在該插件運(yùn)行之前或者之后運(yùn)行某些插件,可以是一個(gè)或者多個(gè)
import postcssSimpleVars from 'postcss-simple-vars';
postcssPresetEnv({
insertBefore: {
'all-property': postcssSimpleVars
}
})
autoprefixer: 設(shè)為 false 可以禁用該功能
preserve: 決定所有插件是否應(yīng)接收同一個(gè)preserve選項(xiàng)逃沿,該選項(xiàng)可以保留或刪除以其他方式填充的 CSS
importFrom: 從外部導(dǎo)入相關(guān)變量信息(如自定義媒體婴渡、自定義屬性幻锁、自定義選擇器和環(huán)境變量),這個(gè)導(dǎo)入的數(shù)據(jù)源可以是 css边臼、js 或者 json (還支持函數(shù)和直接對(duì)象傳值)哄尔。這個(gè)功能完全可以根據(jù)運(yùn)行時(shí)的 ENV 和某些自己設(shè)置的參數(shù),來(lái)決定最基礎(chǔ)的變量參數(shù)柠并,來(lái)進(jìn)行換膚或者針對(duì)PC岭接,H5單獨(dú)出套 ui,這樣能減少 ui 中樣式的大芯视琛(如果本身使用的就是
postcss.config.js
的方式進(jìn)行配置鸣戴,可以把切環(huán)境的功能放到這個(gè)配置文件中,然后動(dòng)態(tài)的加載不同的css)
postcssPresetEnv({
importFrom: [
/*
@custom-media --small-viewport (max-width: 30em);
@custom-selector :--heading h1, h2, h3;
:root { --color: red; }
*/
'path/to/file.css',
/* module.exports = {
customMedia: { '--small-viewport': '(max-width: 30em)' },
customProperties: { '--color': 'red' },
customSelectors: { ':--heading': 'h1, h2, h3' },
environmentVariables: { '--branding-padding': '20px' }
} */
'and/then/this.js',
/* {
"custom-media": { "--small-viewport": "(max-width: 30em)" }
"custom-properties": { "--color": "red" },
"custom-selectors": { ":--heading": "h1, h2, h3" },
"environment-variables": { "--branding-padding": "20px" }
} */
'and/then/that.json',
{
customMedia: { '--small-viewport': '(max-width: 30em)' },
customProperties: { '--color': 'red' },
customSelectors: { ':--heading': 'h1, h2, h3' },
environmentVariables: { '--branding-padding': '20px' }
},
() => {
const customMedia = { '--small-viewport': '(max-width: 30em)' };
const customProperties = { '--color': 'red' };
const customSelectors = { ':--heading': 'h1, h2, h3' };
const environmentVariables = { '--branding-padding': '20px' };
return { customMedia, customProperties, customSelectors, environmentVariables };
}
]
});
- exportTo: 與importFrom功能相反瘟栖,這個(gè)是導(dǎo)出相關(guān)變量(這里應(yīng)該是鼓勵(lì)我們把變量都放在一個(gè)公共的文件下葵擎,這樣便于維護(hù))
stage 2及以上的css語(yǔ)法
就是開啟默認(rèn)配置可以直接使用的css語(yǔ)法
- all: 定義元素的所有屬性的重置的屬性 [stage 3 下面以數(shù)字簡(jiǎn)寫]
a {
all:initial ;
}
- :any-link 用于匹配錨元素的偽類,不管是否被訪問(wèn)(一般情況下a標(biāo)簽被點(diǎn)擊后a標(biāo)簽會(huì)使用:visited的設(shè)置信息半哟,這個(gè)的屬性的設(shè)置不受影響) [2]
nav:any-link> span {
background-color:yellow ;
}
-
break屬性:用于定義多列布局中中斷行為的屬性 [3]
- break-inside: 描述了在多列布局頁(yè)面下的內(nèi)容盒子如何中斷
- break-after: 描述在生成的盒子之后的頁(yè)面酬滤,列或區(qū)域中斷行為
- break-before: 描述列或區(qū)域在生成的盒子之前應(yīng)如何處理中斷
case-insensitive attributes:(看不明白,看意思是不區(qū)分大小寫) [2]
custom properties:用于定義CSS屬性接受的自定義值 [3]
img {
--some-length: 32px;
height: var(--some-length);
width: var(--some-length);
}
- :dir偽類 基于方向性匹配元素的偽類 [2]
- double-position-gradients: 圓錐形漸變[2]
.pie_chart {
background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg);
}
- :focus-visible: 焦點(diǎn)可見的偽類 [2]
- :focus-within: 處于焦點(diǎn)狀態(tài)的偽類 [2]
- font-variant: 設(shè)置小型大寫字母的字體顯示文本寓涨,這意味著所有的小寫字母均會(huì)被轉(zhuǎn)換為大寫盯串,但是所有使用小型大寫字體的字母與其余文本相比,其字體尺寸更小 [3]
- gap屬性 [3]
該屬性是用來(lái)設(shè)置網(wǎng)格行與列之間的間隙(gutters)戒良,是row-gap 和 column-gap的簡(jiǎn)寫形式
- gray(): 用于指定完全去飽和顏色的功能 [2]
- alpha:十六進(jìn)制顏色表示法 比一般的3/6表示法体捏,多1/2個(gè)字符,可以指定透明度 [2]
- hwb(): 用于通過(guò)色調(diào)指定顏色然后將白度和黑度指定為混合的功能 [2]
- image-set(): 根據(jù)用戶分辨率指定引用不同的圖像源 [2]
// resolve是postcss-assets的功能糯崎,下面有介紹
.foo {
background-image: image-set(resolve('logo1x.jpg') 1x,
resolve('logo2x.jpg') 2x,
resolve('logo-print.jpg') 600dpi);
}
...
// become
.foo {
background-image: url(resolve('logo.jpg'));
}
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {.foo {
background-image: url(resolve('logo.jpg'));
}
}
@media (-webkit-min-device-pixel-ratio: 6.25), (min-resolution: 600dpi) {.foo {
background-image: url(resolve('logo.jpg'));
}
}
- lab() 使用lab表示顏色 [2]
- lch() 使用lch表示顏色 [2]
- logical properties and values(流相對(duì)的屬性和值) [2]
span:first-child {
float: inline-start;
margin-inline-start: 10px;
}
- :matches 匹配偽類几缭,可以一次設(shè)置多個(gè)屬性值 [2]
p:matches(:first-child, .special) {
margin-top: 1em;
}
- :not 否定偽類,設(shè)置不在當(dāng)前范圍 [2]
p:not(:first-child, .special) {
margin-top: 1em;
}
- 媒體查詢范圍 使用普通比較符合定義范圍 [3]
@media (width < 480px) {}
@media (480px <= width < 768px) {}
@media (width >= 768px) {}
- overflow 溢出屬性設(shè)置 [2]
- overflow-wrap 定義是否在單詞中插入換行符來(lái)防止溢出屬性 [2]
- place 定義對(duì)齊屬性 [2]
- rebeccapurple 一個(gè)特殊的顏色值 [2]
html {
color:rebeccapurple ;
}
- system-ui 匹配通用字體 [2]
body {
font-family:system-ui ;
}
stage 1 的css語(yǔ)法
因?yàn)樵O(shè)定的stage為2沃呢,如果要啟用需要在features配置中開啟年栓,對(duì)應(yīng)的id可以在插件api中查看,對(duì)應(yīng)的id就是英文加中劃線薄霜,有感覺對(duì)不上的可以去對(duì)應(yīng)github的js文件中查看
postcssPresetEnv({
stage: 2,
browsers: ['> 1%'],
features: {
'nesting-rules': true,
'custom-media-queries': true,
'custom-selectors': true
}
})
- 自定義媒體查詢
@custom-media --small-viewport (max-width: 30em);
@media (--small-viewport) {
h1 {font-size: 16px}
}
...
// 轉(zhuǎn)碼為
@media (max-width: 30em) {
h1 {font-size: 16px}
}
最大最小寬度某抓,可以使用>=
<=
代替
@custom-media --small-viewport (width >= 500px) and (width <= 1200px);
@media (--small-viewport) {
h1 {font-size: 16px}
}
...
// 轉(zhuǎn)為
@media (min-width: 500px) and (max-width: 1200px) {
h1 {font-size: 16px}
}
- 自定義選擇器
CSS 擴(kuò)展規(guī)范(CSS Extensions)中允許創(chuàng)建自定義選擇器,可以使用@custom-selector”來(lái)定義自定義選擇器
@custom-selector :--heading h1, h2, h3, h4, h5, h6;
:--heading {
font-weight: bold;
}
運(yùn)行后變?yōu)?/p>
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: bold;
}
stage 0的css語(yǔ)法
- 嵌套(使用的場(chǎng)景很多惰瓜,也一并開啟使用)
減少重復(fù)的選擇器聲明否副,通過(guò)兩種方式進(jìn)行嵌套:第一種方式要求嵌套的樣式聲明使用“&”作為前綴,“&”只能作為聲明的起始位置崎坊;第二種方式的樣式聲明使用“@nest”作為前綴备禀,并且“&”可以出現(xiàn)在任意位置
// 嵌套只能使用&開頭,除非前綴有@nest
.message {
font-weight: normal;
& .header {
font-weight: bold;
}
@nest .body & {
color: black;
}
}
運(yùn)行后
.message {
font-weight: normal
}
.message .header {
font-weight: bold;
}
.body .message {
color: black;
}
postcss-assets
引用外部資源時(shí),可以通過(guò)這個(gè)插件設(shè)置資源查找路徑痹届,簡(jiǎn)化在樣式文件中插入圖片的操作
安裝
npm i --save-dev postcss-assets
// 設(shè)置loadPaths指定查找路徑
assets({
loadPaths: ['src/images']
}),
這時(shí)如果在main.css的文件中呻待,如果這么設(shè)置一個(gè)類
// 配置resolve,指定在查找路徑下,搜索圖片
.logo {
background-image: resolve('logo.jpg');
}
...
// 編譯后會(huì)變成,自動(dòng)識(shí)別了
.logo {
background-image: url('/src/images/logo.jpg');
}
這里會(huì)要求圖片是目錄下是存在的队腐,如果不存在進(jìn)行編譯時(shí)會(huì)報(bào)錯(cuò),loadPaths 是個(gè)數(shù)組奏篙,相當(dāng)于是多個(gè)搜索的目錄柴淘,只要圖片在某一個(gè)目錄下即可,不過(guò)從編譯時(shí)性能角度來(lái)考慮秘通,一定不可以設(shè)置過(guò)多的目錄为严,否則一定會(huì)影響編譯速度
postcss-assets 還有其他幾項(xiàng)設(shè)置:
- basePath: 如果postcss.config.js不在項(xiàng)目的根目錄可以使用這個(gè)參數(shù)就行修改,比如我這里肺稀,就是把配置文件在根目錄下第股,這樣我在設(shè)置loadPaths時(shí),不用再去考慮其他路徑的問(wèn)題话原,可以從當(dāng)前位置夕吻,直接設(shè)置圖片目錄為src/images,一般這種配置文件感覺放在根目錄最好繁仁,這樣可以很方便別人查看
- baseUrl: 沒特別弄明白這參數(shù)是什么意思涉馅,好像是在服務(wù)器運(yùn)行時(shí),設(shè)置url黄虱,不過(guò)理解不了稚矿,部署到生產(chǎn)環(huán)境的代碼,肯定時(shí)編譯后的代碼捻浦,不能在線上再實(shí)時(shí)編譯吧晤揣。。朱灿。
- cachebuster: 是否設(shè)置緩存昧识,默認(rèn)是false
// 比如如果設(shè)為true,圖片后就會(huì)加一串hash值
.logo {
background-image: url('/src/images/logo.jpg?1637e45dd90');
}
- loadPaths: 設(shè)置查找特定目錄
- relative: 和URL解析有關(guān)母剥,沒試出來(lái)做什么用的滞诺。。环疼。使用默認(rèn)的false习霹,禁用相對(duì)url解析
- cache: 默認(rèn)為false,如果引入文件沒有發(fā)生變化炫隶,則有限使用緩存文件淋叶,感覺應(yīng)該和cachebuster配套使用,能提升編譯速度
另外這個(gè)插件伪阶,還支持通過(guò)圖片進(jìn)行相關(guān)設(shè)置
- inline: 是把圖片轉(zhuǎn)成base64文件煞檩,估計(jì)要慎用处嫌,如果圖片很多的話,會(huì)影響編譯速度
- width: 是獲取一張圖片的寬度斟湃,height是獲取一張圖片的高度
.logo {
background-image: inline('logo.jpg');
width: width('logo.jpg');
height: height('logo.jpg');
}
...
// 運(yùn)行后
.logo {
background-image: ...base64的圖片
width: 493px;
height: 448px;
}
cssnano
webpack4+
的版本熏迹,已經(jīng)集成了cssnano,mode 設(shè)為生產(chǎn)模式就會(huì)自動(dòng)啟用這個(gè)插件
npm install --save-dev cssnano
// 如果單獨(dú)使用凝赛,可以這么配置
module.exports = {
plugins: [
require('cssnano')({
preset: 'default',
}),
],
};
使用 postcss 實(shí)現(xiàn)一個(gè) sass
postcss 可自主定義相關(guān)插件的使用注暗,組合出適合自己使用的功能,借助 postcss 的插件來(lái)實(shí)現(xiàn)一個(gè)類 sass
相關(guān)插件介紹
- postcss 基礎(chǔ)功能包
- postcss-advanced-variables 提供嵌套類似 sass 的變量墓猎、@if捆昏、@else、@for毙沾、@each骗卜、@mixin、@include左胞、@content
- postcss-scss 使 postcss 中可以正常使用 sass 中的
#{$var-name}
變量形式 - postcss-apply
- postcss-assets
- postcss-import 使在.pcss文件可以使用@import引入樣式文件
- postcss-preset-env 一個(gè)對(duì)未來(lái)css語(yǔ)法規(guī)則寇仓,實(shí)現(xiàn)比較好的插件
- postcss-cli 提供了終端運(yùn)行的能力
@import
使用 postcss-import 插件
const atImport = require("postcss-import");
module.exports = {
plugins: [
atImport(),
元素嵌套
使用 postcss-preset-env 插件 stage:0
中的 nesting-rules
require('postcss-preset-env')({
stage: 2,
browsers: ['> 1%'],
features: {
'nesting-rules': true
}
})
具體寫法上和sass嵌套的寫法有些不一樣,不過(guò)這種寫法是未來(lái)css的標(biāo)準(zhǔn)罩句,以這個(gè)為主要寫法
nav {
& ul {
margin: 0;
padding: 0;
list-style: none;
}
& li {
display: inline-block;
}
& a {
display: block;
padding: 6px 12px;
text-decoration: none;
& span {
color: $red;
}
}
}
變量焚刺、@if、@else门烂、@for乳愉、@each、@mixin屯远、@include蔓姚、@content
使用 postcss-advanced-variables 這個(gè)插件,這個(gè)插件能實(shí)現(xiàn)sass變量的大部分功能慨丐,不過(guò)一個(gè)特殊的語(yǔ)法#{$var-name}
需要使用到 postcss-scss 這個(gè)插件坡脐,并且在postcss.config.js
中設(shè)置 parser
為 postcss-scss
const advanced = require("postcss-advanced-variables");
module.exports = {
parser: "postcss-scss",
plugins: [
advanced(),
...
// 變量
$font-size: 1.25em;
$font-stack: "Helvetica Neue", sans-serif;
$primary-color: #333;
body {
font: $font-size $(font-stack);
color: #{$primary-color};
}
...
// 轉(zhuǎn)為
body {
font: 1.25em "Helvetica Neue", sans-serif;
color: #333;
}
// @if、@else
$type: monster;
p {
@if $type == ocean {
color: blue;
} @else {
color: black;
}
}
...
// 轉(zhuǎn)為
p {
color: black
}
// @for
@for $i from 1 through 5 by 2 {
.width-#{$i} {
width: #{$i}0em;
}
}
...
// 轉(zhuǎn)為
.width-1 {
width: 10em;
}
.width-3 {
width: 30em;
}
.width-5 {
width: 50em;
}
// @each
@each $animal in (red, yellow, black, white) {
.#{$animal}-icon {
color: #{$animal};
}
}
...
// 轉(zhuǎn)為
.red-icon {
color: red;
}
.yellow-icon {
color: yellow;
}
.black-icon {
color: black;
}
.white-icon {
color: white;
}
// @mixin @include
@mixin heading-text {
color: #242424;
font-size: 4em;
}
h1, h2, h3 {
@include heading-text;
}
...
// 轉(zhuǎn)為
h1,
h2,
h3 {
color: #242424;
font-size: 4em;
}
屬性嵌套
postcss-nested-props
const nestedProps = require("postcss-nested-props");
module.exports = {
plugins: [
nestedProps(),
.funky {
font: {
family: fantasy;
size: 30em;
weight: bold;
}
}
...
// 轉(zhuǎn)為
.funky {
font-family: fantasy;
font-size: 30em;
font-weight: bold
}
Extend/Inheritance(擴(kuò)展/繼承)
postcss-extend
const extend = require("postcss-extend");
module.exports = {
plugins: [
extend(),
// 這里和sass有點(diǎn)不同房揭,使用 @define-placeholder 而非 % 導(dǎo)出樣式塊
@define-placeholder message-shared {
border: 1px solid #ccc;
padding: 10px;
color: #333;
}
.message {
@extend message-shared;
}
.error {
border: 1px #f00;
background-color: #fdd;
}
.seriousError {
@extend .error;
border-width: 3px;
}
...
// 轉(zhuǎn)為
.message {
border: 1px solid #ccc;
padding: 10px;
color: #333;
}
.error, .seriousError {
border: 1px #f00;
background-color: #fdd;
}
.seriousError {
border-width: 3px;
}
添加calc()計(jì)算
postcss-calc
const calc = require("postcss-calc");
module.exports = {
plugins: [
calc(),
@mixin columns_calc($count) {
width: calc(100% / $count);
@if $count > 1 {
float: left;
}
}
.column_calculated {
@include columns_calc(2);
}
...
// 轉(zhuǎn)為
.column_calculated {
width: 50%;
float: left;
}
添加了這些插件备闲,基本就可以完全可以滿足正常開發(fā)需求
完整配置如下:
const postcssPresetEnv = require("postcss-preset-env");
const atImport = require("postcss-import");
const advanced = require("postcss-advanced-variables");
const nestedProps = require("postcss-nested-props");
const extend = require("postcss-extend");
const calc = require("postcss-calc");
module.exports = {
parser: "postcss-scss",
plugins: [
atImport(),
advanced(),
nestedProps(),
extend(),
calc(),
postcssPresetEnv({
stage: 2,
browsers: "> 3%",
features: {
"nesting-rules": true
}
})
]
};
獨(dú)立使用postcss
可以通過(guò) postcss-cli 這個(gè)插件構(gòu)建一個(gè)獨(dú)立使用的 css 處理平臺(tái),可在 package.json 中添加如下命令
"scripts": {
"build:pc": "npx postcss src/main.pc.css -o dist/main.pc.css",
"build:h5": "npx postcss src/main.h5.css -o dist/main.h5.css"
// src/main.pc.css
@import 'normalize.css';
@import 'reset.css';
@import 'variables.css';
@import 'common.css';
@import 'common.mixin.css';
@import 'layout.mixin.css';
@import 'layout.css';
@import 'layout-flex.css';
@import 'button.mixin.css';
@import 'button.css';
@import 'button-group.css';
@import 'skeleton.mixin.css';
@import 'skeleton.css';
@import 'breadcrumb.css';
@import 'dropdown.css';
@import 'menu.css';
@import 'pagination.mixin.css';
@import 'pagination.css';
@import 'step.css';
@import 'checkbox.css';
@import 'cascader.css';
@import 'form.css';
@import 'calendar.css';
@import 'input-number.css';
@import 'rate.css'
這里由一個(gè)統(tǒng)一入口文件捅暴,控制針對(duì)PC恬砂,H5不同的樣式表的輸出,在入口文件中蓬痒,可以設(shè)置引入不同的變量(比如上面例子中的 variables.css 正常開發(fā)中泻骤,可以細(xì)化成variables.pc.css或者variables.orange.css 這類的樣式),讓換膚類的功能也比較容易實(shí)現(xiàn)
避免編譯器對(duì)pcss文件報(bào)錯(cuò)
我使用的是我使用的是vscode,引用插件后寫的樣式狱掂,編譯器基本是不認(rèn)識(shí)的演痒,會(huì)給你報(bào)錯(cuò),所以這里說(shuō)下如何避免對(duì)pcss的報(bào)錯(cuò)趋惨,其他編譯器應(yīng)該也有類似的方法
對(duì)vscode添加對(duì).pcss文件的支持
- 安裝postcss-sugar-language插件
- 進(jìn)入setting鸟顺,搜索files.associations在其中添加如下內(nèi)容
"*.css": "postcss"
設(shè)置 "postcss.validate": false
,避免檢查器對(duì) pcss 進(jìn)行檢查
css module
(參考CSS in JS 簡(jiǎn)介)
css module
和css in js
都是社區(qū)針對(duì) css 作用域提出的解決方案器虾,從實(shí)際開發(fā)過(guò)程中诊沪,感覺css module
的方式,更適合分工合作的要求曾撤。
現(xiàn)在開發(fā)中,不管你使用什么框架晕粪,基本的流程大概都是:先做靜態(tài)頁(yè)面挤悉,再接動(dòng)態(tài)數(shù)據(jù)。這里很容易就會(huì)形成兩條工作線:一類專門進(jìn)行重構(gòu)巫湘,與設(shè)計(jì)師装悲、交互對(duì)接完成視覺實(shí)現(xiàn);另一類專門與產(chǎn)品經(jīng)理尚氛、后端對(duì)接業(yè)務(wù)需求(體量大的公司會(huì)拆分成兩個(gè)工種诀诊,小公司自然是全干了,但是工作場(chǎng)景多半如此)阅嘶。
css in js
的方式属瓣,更符合獨(dú)立組件的封裝型。從樣式讯柔、邏輯到內(nèi)容展現(xiàn)抡蛙,在一個(gè) js 中都實(shí)現(xiàn),不需要再引入其他文件魂迄,如果是寫 ui 組件這種方式是極好的粗截。
但是如果是正常的開發(fā)需求,你用這種方式捣炬,就表示樣式問(wèn)題的改動(dòng)熊昌、修復(fù),業(yè)務(wù)邏輯的實(shí)現(xiàn)湿酸,都是在一個(gè)文件中進(jìn)行婿屹,不利于分工合作。
個(gè)人感覺 css in js
方式會(huì)讓 js 文件變得混亂稿械,可讀性下降(正常開發(fā)就算是狀態(tài)管理选泻,一般都會(huì)被拆分成一個(gè)個(gè)獨(dú)立的文件)。而且沒辦法單獨(dú)輸出樣式文件,沒辦法把樣式文件丟在某個(gè) cdn 服務(wù)器下页眯,也影響組件的復(fù)用性梯捕。如果要復(fù)用某個(gè)組件(業(yè)務(wù)組件)就表示要接受這個(gè)組件自帶的樣式,稍微調(diào)整點(diǎn)字號(hào)顏色啥的窝撵,就要單獨(dú)加個(gè)接收參數(shù)傀顾,或者新建個(gè)類似 list-red
的新組件(如果是引入樣式的方式,完全可以通過(guò)再引入這個(gè)組件的外層加個(gè)類似 <div class='red-list'><list /></div>
碌奉,在外層樣式文件中直接控制短曾,也很容易擴(kuò)展多個(gè)不同樣式、換膚啥的)赐劣。
css in js
方式對(duì)重構(gòu)人員也不友好嫉拐,他們之前查看樣式問(wèn)題,直接修改樣式文件部署后就能看出問(wèn)題能不能解決魁兼,現(xiàn)在需要修改 js 文件等js文件部署后才能查看改動(dòng)是否生效(如果再碰到分支不同婉徘,版本不同的情況,那更熱鬧了咐汞。盖呼。。)
啟用
參考了 CSS Modules 用法教程
配合 css-loader
使用化撕,在 webpack
配置項(xiàng)中如下設(shè)置:
{test: /\.pcss/, use: [MiniCssExtractPlugin.loader, 'css-loader?modules', 'postcss-loader']}几晤,
這樣就開啟了 css module
,它的使用會(huì)把對(duì)應(yīng)的樣式名變成一種有規(guī)律植阴,但不可預(yù)期的名稱蟹瘾,比如
/// main.pcss
/// 由于樣式文件本身并沒有要求 .classname 不能重復(fù),所以要自己保證不要重復(fù)墙贱,否則針對(duì)同一類名會(huì)轉(zhuǎn)出多個(gè)變量名热芹,在使用時(shí)會(huì)有問(wèn)題
.box {
border-radius:5px;
}
.info {
color: red;
font-size: 24px;
}
...
/// app.vue
<template>
<div :class="$style.info">{{ msg }}</div>
</template>
import style from '../style/main.pcss';
...
computed: {
$style () {
return style;
}
}
$style
的使用方式參考了 vue-loader 的 CSS Modules 方案,vue loader 會(huì)使用$style
的計(jì)算屬性惨撇,向組件注入 CSS Modules 局部對(duì)象
style 會(huì)輸出為(value 值是一個(gè)動(dòng)態(tài)值)
{box: "_2sI8WybUY_1NGPVWmXjdbV", info: "_hA0iOLbXZy9PpOuCjpkc"}
組件內(nèi)直接使用其中的定義的樣式名伊脓,會(huì)自動(dòng)替換成這些名稱,樣式文件也會(huì)自動(dòng)轉(zhuǎn)成這些名稱魁衙,這樣可以解決 css 的樣式?jīng)_突(污染)的問(wèn)題报腔,全局污染的問(wèn)題,也可以算是解決依賴的問(wèn)題剖淀,組件只需要引入自己相關(guān)的樣式纯蛾,在這個(gè)相關(guān)樣式文件中定義自己需要使用的樣式,再通過(guò) $style
的形式給相關(guān)組件使用纵隔。
vue
的寫法稍微麻煩點(diǎn)(如果用 JSX 會(huì)簡(jiǎn)單些)翻诉,如果是在 react
中可以直接使用
import style from '../style/main.css';
class App extends Component {
render () {
return <div className={style.info}>app info</div>
}
}
全局作用域
在引入的樣式文件中炮姨,默認(rèn)會(huì)對(duì)所有樣式進(jìn)行轉(zhuǎn)換,如果你的樣式只是想通過(guò)普通方式使用碰煌,可以有兩種方案:
- 只針對(duì)
.pcss
開啟css module
舒岸,.css
不開啟
/// webpack.config.js
{test: /\.css/, use: [MiniCssExtractPlugin.loader, 'css-loader']},
{test: /\.pcss/, use: [MiniCssExtractPlugin.loader, 'css-loader?modules', 'postcss-loader']}
...
/// global.css
body {
font-size: 18px;
background: #cccccc;
}
...
/// app.vue
import '../style/global.css';
import style from '../style/main.pcss'; // 這里雖然是分開導(dǎo)入,但是最終會(huì)合并和一個(gè)樣式文件
...
/// main.css 導(dǎo)出的樣式文件
body {
font-size: 18px;
background: #cccccc;
}
._2sI8WybUY_1NGPVWmXjdbV {
border-radius:5px;
}
._hA0iOLbXZy9PpOuCjpkc {
color: red;
font-size: 24px;
}
- 在待編譯的樣式文件使用
:global(.className)
(也可以省略為:global .className
)的寫法芦圾,這樣這個(gè)對(duì)應(yīng)的樣式也不會(huì)編譯
:local 可以設(shè)置哪些需要轉(zhuǎn)蛾派,因?yàn)槟J(rèn)就是轉(zhuǎn)換,沒必要再加一層說(shuō)明其需要轉(zhuǎn)換
對(duì)于需要轉(zhuǎn)換的个少,請(qǐng)一直使用 .classname洪乍,不要使用 id
/// main.pcss
...
:global(body) {
font-size: 18px;
background: #cccccc;
}
Composing(組合) 及 Importing(導(dǎo)入)
組合的意義并不是把樣式代碼進(jìn)行混合,而是在于使用了組合的類名夜焦,在引用時(shí)會(huì)包含其組合的子類
.box {
border-radius:5px;
}
.info {
color: red;
font-size: 24px;
}
.foo {
composes: box;
composes: info;
padding: 10px;
}
/// 經(jīng)過(guò)轉(zhuǎn)換后對(duì)應(yīng)的json信息如下
box: "src-style-main__box--2sI8W",
info: "src-style-main__info--_hA0i",
foo: "src-style-main__foo--LiN2X src-style-main__box--2sI8W src-style-main__info--_hA0i",
/// 如果我們使用 $style.foo 還會(huì)包含其他兩個(gè)子類的內(nèi)容
composes
還可以從其他樣式模塊中導(dǎo)入樣式進(jìn)行組合
.foo {
composes: main-title header-title from './color.css';
padding: 10px;
}
@value
css 變量的解決方案很多壳澳,這個(gè)是 css-loader
的方案
官方有個(gè)命名建議:v- 定義value值, s- 選擇器 m- 定義 media 規(guī)則
@value v-primary: #BF4040;
@value s-black: black-selector;
@value m-large: (min-width: 960px);
.header {
color: v-primary;
padding: 0 10px;
}
:global .s-black {
color: black;
}
@media m-large {
.header {
padding: 0 20px;
}
}
定制編譯后的類名
css-loader
默認(rèn)的哈希算法是 [hash:base64]
,轉(zhuǎn)出的就是這種 _2sI8WybUY_1NGPVWmXjdbV
茫经,這個(gè)轉(zhuǎn)換后的名稱是可以定制的
// 參數(shù)比較長(zhǎng)钾埂,再使用拼接的寫法,看起來(lái)不美觀
loader: 'css-loader',
options: {
modules: {
localIdentName: '[path][name]__[local]--[hash:base64:5]'
} // 注意是在 modules 下設(shè)置 localIdentName
}
按官方建議
- 開發(fā)環(huán)境使用
[path][name]__[local]--[hash:base64:5]
- 生產(chǎn)環(huán)境使用
[hash:base64]
這樣轉(zhuǎn)出的類名就類似 src-style-main__box--2sI8W
科平,能看出路徑和使用模塊,方便定位樣式問(wèn)題所在的
css loader 參數(shù)
名稱 | 類型 | 默認(rèn) | 描述 |
---|---|---|---|
url | {Boolean|Function} | true | 啟用/禁止 url() 功能 |
import | {Boolean|Function} | true | 啟用/禁用 @import 處理 |
modules | {Boolean|String|Object} | false | 啟用/禁用 CSS Modules 以及相關(guān)配置 |
sourceMap | {Boolean} | false | 啟用/禁用 map 功能 |
importLoaders | {Number} | 0 | 在 css-loader 之前使用多少個(gè)加載器(默認(rèn)姜性,別去動(dòng)這個(gè)值瞪慧,按 webpack 中的設(shè)置的 use 順序去執(zhí)行使用 loader) |
localsConvention | {String} | 'asIs' | 導(dǎo)出的 JSON 對(duì)應(yīng)的 Key 的規(guī)則 |
onlyLocals | {Boolean} | false | 影響打包時(shí)的 loader 順序,一些 SSR 場(chǎng)景下可以需要設(shè)置這個(gè)值部念,一般情況下別用 |
esModule | {Boolean} | false | 是否啟用 es module |
url
/// 先安裝 url-loader 處理圖片弃酌,并添加相關(guān)配置信息
{
test: /\.(png|svg|jpg|jpeg|gif)$/,
use: "url-loader"
},
...
/// main.pcss
.foo {
color: red;
font-size: 14px;
background: url("../image/timg.jpeg"); // 此處設(shè)定了背景圖
}
按如上設(shè)置,轉(zhuǎn)換出的 css 會(huì)對(duì)圖片進(jìn)行處理儡炼,但如果設(shè)置這個(gè)值為 false
{
loader: "css-loader",
options: {
modules: true,
url: false // 這個(gè)值默認(rèn)是 true
}
},
轉(zhuǎn)換出的 css 就不會(huì)對(duì) url()
進(jìn)行處理妓湘,原樣輸出
/// 不如處理 background: url("../image/timg.jpeg");
/// 這個(gè) url 還可以設(shè)置為函數(shù),在這里可以控制乌询,只有指定圖片名會(huì)轉(zhuǎn)榜贴,進(jìn)行差異化處理
url: (url, resourcePath) => {
// url ../image/timg.jpeg
// resourcePath - css 的絕對(duì)路徑
// 不處理 `img.png` urls
if (url.includes('img.png')) {
return false;
}
return true;
},
import
這個(gè)值和 url 功能類似,只不過(guò)這里是控制文件的導(dǎo)入導(dǎo)出妹田,這個(gè)值也一樣可以設(shè)置 true 或 false
唬党,如果這樣直接設(shè)置,那這肯定有問(wèn)題鬼佣,這個(gè)參數(shù)要么不設(shè)置驶拱,要設(shè)置一定是要對(duì)url進(jìn)行過(guò)濾
/// @import "./color.css";
import: (parsedImport, resourcePath) => {
// parsedImport { url: './color.css', media: '' }
// parsedImport.url - `@import` 文件時(shí)對(duì)應(yīng)的路徑
// parsedImport.media - `@import` 媒體查詢時(shí)對(duì)應(yīng)的路徑
// resourcePath - css 文件的絕對(duì)路徑
// 包含 `style.css` 不進(jìn)行合并處理
if (parsedImport.url.includes('style.css')) {
return false;
}
return true;
},
@import 是一個(gè)廣泛被支持的 css 屬性,大于 IE9 的瀏覽器就可以正常使用
modules
true 或 false
啟用/禁止(還可以通過(guò)設(shè)置 modules 的值為 'local'
或 'global'
啟用/禁止) css modules
前面提到的 :global :local
晶衷、Composing Importing
蓝纲、@value
阴孟、localIdentName
都是 modules 的配置信息,modules 可以接收一個(gè)對(duì)象進(jìn)行其他配置
modules: {
mode: 'local', // 設(shè)置 local 啟用 global 禁用 css 模塊
exportGlobals: true,
localIdentName: '[path][name]__[local]--[hash:base64:5]', // 編譯后的類名
context: path.resolve(__dirname, 'src'),
hashPrefix: 'my-custom-hash',
},
-
mode
除了local global
外税迷,還有一個(gè)值是pure
永丝,使用這個(gè)值就要求樣式文件中必須是純的選擇器,不能使用global local
進(jìn)行包裹
/// 在 mode 為 pure 時(shí)翁狐,會(huì)提示編譯出錯(cuò)
:local(.zoo)
...
/// mode 還可以接受一個(gè)函數(shù)形式类溢,對(duì)指定路徑的樣式文件進(jìn)行特殊處理(什么文件開啟轉(zhuǎn)換,什么文件不開啟)露懒,返回值只能是這三個(gè)值
mode: (resourcePath) => {
if (/pure.css$/i.test(resourcePath)) {
return 'pure';
}
if (/global.css$/i.test(resourcePath)) {
return 'global';
}
return 'local';
},
exportGlobals
按描述應(yīng)該是控制輸出類名的名稱闯冷,不過(guò)沒沒查出有什么特別的用處,設(shè)不設(shè)都不影響使用context
生成hash值相同懈词,參考那個(gè) GitHub bug 說(shuō)明蛇耀,是在某些情況下,生成的hash值出現(xiàn)重復(fù)的情況坎弯,然后借助這個(gè)參數(shù)纺涤,解決此問(wèn)題,不過(guò)我試了很多情況抠忘,沒試出來(lái)生成 hash 相同的情況hashPrefix
設(shè)定組自己的 hash 值規(guī)則撩炊,一般無(wú)須設(shè)置getLocalIdent
設(shè)置編譯后的規(guī)則名,同localIdentName
只不過(guò)這是個(gè)函數(shù)崎脉,能設(shè)置的更細(xì)拧咳,一般用localIdentName
localIdentRegExp
沒試出干什么用
localsConvention
這個(gè)設(shè)定導(dǎo)出 JSON 時(shí),key值和類名如何映射囚灼,默認(rèn)值是 'asIs'
loader: 'css-loader',
options: {
modules: {
mode: 'local',
localIdentName: '[path][name]__[local]--[hash:base64:5]'
},
localsConvention: 'asIs'
}
...
.infoNews {
font-size: 35px;
}
.info-old {
color: white;
}
.info_dashes {
color: salmon;
}
.info {
color: red;
}
...
/// 默認(rèn) asIs骆膝,類名是啥,導(dǎo)出的就是啥
info: "src-components-page1-index__info--10GK2"
info-old: "src-components-page1-index__info-old--k163w"
infoNews: "src-components-page1-index__infoNews--1uma1"
info_dashes: "src-components-page1-index__info_dashes--FVVUn"
...
/// camelCase 駝峰灶体,會(huì)把非駝峰的命名轉(zhuǎn)為駝峰阅签,并保留之前的類名
info: "src-components-page1-index__info--10GK2"
info-old: "src-components-page1-index__info-old--k163w"
infoDashes: "src-components-page1-index__info_dashes--FVVUn" // 值同 info_dashes
infoNews: "src-components-page1-index__infoNews--1uma1"
infoOld: "src-components-page1-index__info-old--k163w" // 值同 info-old
info_dashes: "src-components-page1-index__info_dashes--FVVUn"
...
/// camelCaseOnly 與駝峰類似,只不過(guò)不會(huì)保留非駝峰的轉(zhuǎn)換
info: "src-components-page1-index__info--10GK2"
infoDashes: "src-components-page1-index__info_dashes--FVVUn"
infoNews: "src-components-page1-index__infoNews--1uma1"
infoOld: "src-components-page1-index__info-old--k163w"
...
/// dashes 一樣也是轉(zhuǎn)駝峰蝎抽,只不過(guò)這里限制只轉(zhuǎn) ``-`` 號(hào)
info: "src-components-page1-index__info--10GK2"
info-old: "src-components-page1-index__info-old--k163w"
infoNews: "src-components-page1-index__infoNews--1uma1"
infoOld: "src-components-page1-index__info-old--k163w"
info_dashes: "src-components-page1-index__info_dashes--FVVUn" // 不轉(zhuǎn)換
...
/// dashesOnly 不保留轉(zhuǎn)換前的
info: "src-components-page1-index__info--10GK2"
infoNews: "src-components-page1-index__infoNews--1uma1"
infoOld: "src-components-page1-index__info-old--k163w"
info_dashes: "src-components-page1-index__info_dashes--FVVUn"
之所以會(huì)有這么個(gè)參數(shù)政钟,是因?yàn)槲覀冊(cè)谑褂? css modules
時(shí),最終可能會(huì)動(dòng)態(tài)綁定到某個(gè)組件上樟结,這是為了方便在 js 中使用