做者:凹凸曼-冥冥javascript
小程序的簡化版 css-modules,比標準 css-modules 代碼量更少的優化方案css
css-modules 是一種 css 模塊化方案,它在構建過程當中生成一個原類名與新類名的 map,根據 map 引用樣式,經過設定 hash 規則,實現了對 CSS 類名做用域的限定,它一般用來解決頁面類名衝突的問題。因爲微信小程序內組件樣式默認隔離,爲何要使用 css-modules 呢?java
有如下 2 個緣由:webpack
weapp-css-modules 作了哪些事?git
標準 css-modules 方案:github
import style from './index.wxss' <view class="{{style.banner}}"></view> .index_banner_xkpkl { xx } module.exports ={'banner' : 'index_banner_xkpkl'} // 額外生成的 map 文件
weapp-css-modules 編譯後效果:web
let style = {} <view class="a"></view> .a { xx }
目前只開發了適用於使用 gulp 編譯小程序的 gulp 插件,後續計劃開發 webpack 可用的插件實現相同功能npm
npm i gulp-weapp-css-modules gulp-sort
// gulpfile.js const { weappCssModule, wcmSortFn } = require('gulp-weapp-css-modules') const sort = require('gulp-sort'); gulp.task('css-module', () => { return gulp.src('./src/**/*') .pipe(sort(wcmSortFn)) // 因爲處理文件有順序依賴,須要先對文件排序 .pipe(weappCssModule()) .pipe(gulp.dest('./dist')) })
小程序頁面不具有隔離功能,所以只有具有樣式隔離的 Component 能夠改造使用 weapp-css-modulesgulp
一、css 文件更名字: weapp-css-modules 經過 css 文件是否帶 module 來識別須要替換的內容小程序
index.wxss
-> index.module.wxss
// 或者使用 scss/其餘
index.scss
-> index.module.scss
二、js 內新增樣式文件的引入,目的是創建 css-modules 的樣式與 js 關係
import styles from './index.module.wxss data:{ ..., styles:styles }
三、修改 js 內類名的地方替換爲 styles 的間接引入
query.select('.banner') .boundingClientRect() .exec(function (res) {...}) // 改成 query.select('.' + styles['banner']) .boundingClientRect() .exec(function (res) {...})
四、修改 wxml 內類名的使用
4.1. 普通類名
<view class="banner"></view> // 改成 <view class="{{styles.banner}}"></view> // 或者 <view class="{{styles['banner']}}"></view>
4.2. 三目運算符
<view class="banner__dot {{ 'banner__dot--' + (index == swiperCurrent ? 'cur' : '')}"></view> // 改成 <view class="{{styles['banner__dot'] + ' ' + (index == swiperCurrent ? styles['banner__dot--cur'] : '')}}"></view> // 或者 <view class="{{`${style['banner__dot']} ${index == swiperCurrent ? style['banner__dot--cur'] : ''}`}}"></view>
這裏須要注意幾種有問題的寫法:
4.2.1. 類名間未加空格
<view class="{{styles['banner__dot'] + (index == swiperCurrent ? styles['banner__dot--cur'] : '')}}"></view>
4.2.2. 三目表達式未加括號,運算優先級不明
<view class="{{styles['banner__dot'] + ' ' + index == swiperCurrent ? styles['banner__dot--cur'] : ''}}"></view>
4.2.3. styles 的屬性須要是具體的字符串,不能使用變量表達式(這是 weapp-css-modules 須要單獨關注的地方,由於編譯階段會對 styles.xx 進行求值,因此不能把表達式寫在屬性位置)
<view class="{{styles['banner__dot'] + ' ' + styles[index == swiperCurrent ? 'banner__dot--cur': '']}}"></view>
五、構建過程當中關注腳本的紅色提示,相似於這種:
這是因爲在 js/wxml 內使用了一個banner__swiper_2
,而 css 內並無定義banner__swiper_2
,css-module 編譯的 map 文件是根據 css 內的樣式定義來生成 key 名的,所以styles['banner__swiper_2']
是undefined
, 針對這種狀況有兩種處理方式:
5.1. 若是 js 內須要經過這個類名選擇到某個元素,可是 css 內不須要編寫樣式,那麼能夠將它視爲不須要編譯的類名,即:
query.selector('.banner__swiper_2') // 不改爲 styles.xx 的寫法 <view class="banner__swiper_2"></view> // 相應的元素也不索引到 styles // 這樣實現了一個組件內不會被編譯的樣式
5.2. 若是 js 內無引用,那麼刪掉 wxml 內該類名的定義吧~
六、構建完進行檢查,關注樣式和交互是否正常
/demo/gulp-project-demo
歡迎關注凹凸實驗室博客:aotu.io
或者關注凹凸實驗室公衆號(AOTULabs),不定時推送文章。