Vue CSS Modules
CSS Modules:區域性作用域 & 模組化
CSS Modules
為每一個區域性類賦予全域性唯一的類名,這樣元件樣式間就不會相互影響了。如:
/* button.css */
.button {
font-size: 16px;
}
.mini {
font-size: 12px;
}
複製程式碼
它會被轉換為類似這樣:
/* button.css */
.button__button--d8fj3 {
font-size: 16px;
}
.button__mini--f90jc {
font-size: 12px;
}
複製程式碼
當匯入一個 CSS 模組檔案時,它會將區域性類名到全域性類名的對映物件提供給我們。就像這樣:
import styles from `./button.css`
// styles = {
// button: `button__button--d8fj3`,
// mini: `button__mini--f90jc`
// }
element.innerHTML = `<button class="` + styles.button + ` ` + styles.mini + `" />`
複製程式碼
vue-css-modules
:簡化類名對映
下面是一個使用了 CSS Modules 的按鈕元件:
<template>
<button :class="{
`global-button-class-name`: true,
[styles.button]: true,
[styles.mini]: mini
}">點我</button>
</template>
<script>
import styles from `./button.css`
export default {
props: { mini: Boolean },
data: () => ({ styles })
}
</script>
複製程式碼
的確,CSS Modules 對於 Vue 元件是一個不錯的選擇。但也存在以下幾點不足:
- 你必須在
data
中傳入styles
- 你必須使用
styles.localClassName
匯入全域性類名 - 如果有其他全域性類名,你必須將它們放在一起
- 如果要和元件的屬性值繫結,就算區域性類名和屬性名一樣,也要顯式指定
對於上面的按鈕元件,使用 vue-css-modules
後:
<template>
<button
class="global-button-class-name"
styleName="button :mini">
點我
</button>
</template>
<script>
import CSSModules from `vue-css-modules`
import styles from `./button.css`
export default {
mixins: [CSSModules(styles)],
props: { mini: Boolean }
}
</script>
複製程式碼
現在:
- 你不必在
data
中傳入styles
,但得在mixins
中傳入styles
? - 你可以跟
styles.localClassName
說拜拜了 - 將區域性類名放在
styleName
屬性,全域性類名放在class
屬性,規整了許多 - 區域性類名繫結元件同名屬性,只需在其前面加上
:
修飾符
修飾符
@button
<button styleName="@button">按鈕</button>
複製程式碼
這等同於:
<button styleName="button" data-component-button="true">按鈕</button>
複製程式碼
這讓你能在外部重置元件的樣式:
.form [data-component-button] {
font-size: 20px;
}
複製程式碼
$type
<button styleName="$type">按鈕</button>
複製程式碼
這等同於:
<button :styleName="type">按鈕</button>
複製程式碼
:mini
<button styleName=":mini">按鈕</button>
複製程式碼
這等同於:
<button :styleName="mini ? `mini` : ``">按鈕</button>
複製程式碼
disabled=isDisabled
<button styleName="disabled=isDisabled">按鈕</button>
複製程式碼
這等同於:
<button :styleName="isDisabled ? `disabled` : ``">按鈕</button>
複製程式碼
使用方法
在 Vue 模板中使用
引入模板外部的 CSS 模組
<template>
<button
class="global-button-class-name"
styleName="button :mini">
點我
</button>
</template>
<script>
import CSSModules from `vue-css-modules`
import styles from `./button.css`
export default {
mixins: [CSSModules(styles)],
props: { mini: Boolean }
}
</script>
複製程式碼
使用模板內部的 CSS 模組
<template>
<button
class="global-button-class-name"
styleName="button :mini">
點我
</button>
</template>
<script>
import CSSModules from `vue-css-modules`
export default {
mixins: [CSSModules()],
props: { mini: Boolean }
}
</script>
<style module>
.button {
font-size: 16px;
}
.mini {
font-size: 12px;
}
</style>
複製程式碼
在 Vue JSX 中使用
import CSSModules from `vue-css-modules`
import styles from `./button.css`
export default {
mixins: [CSSModules(styles)],
props: { mini: Boolean },
render() {
return (
<button styleName="@button :mini">點我</button>
)
}
}
複製程式碼
在 Vue 渲染函式中使用
import CSSModules from `vue-css-modules`
import styles from `./button.css`
export default {
mixins: [CSSModules(styles)],
props: { mini: Boolean },
render(h) {
return h(`button`, {
styleName: `@button :mini`
}, `點我`)
}
}
複製程式碼
實現原理
vue-css-modules
註冊了 beforeCreate
鉤子,在鉤子中劫持了元件的渲染函式。對於傳給渲染函式的引數,將會解析其 data
或 data.attrs
中的 styleName
屬性生成全域性類名字串,並將它附著在 data.staticClass
值的後面。
Github:vue-css-modules