useCssModule
Vue 开启 cssModule 后,可以通过这个 API 取到经过 vue-loader 处理后的 className。
- HelloWorld.vue
// template
<div :class="$style.hello">text</div>
// script
export default {
setup() {
const $style = useCssModule()
console.log($style.hello); // "HelloWorld_hello_1ae9G"
}
}
// style
<style module>
.hello {
color: red;
}
</style>
源码解析
获取当前组件实例下的 type.__cssModules.$style 对象。
tip: __cssModules 由 vue-loader 注入
function useCssModule(name = '$style') {
if (!__GLOBAL__) {
const instance = getCurrentInstance()!
const modules = instance.type.__cssModules
const mod = modules[name]
if (!mod) {
return EMPTY_OBJ
}
return mod
} else {
return EMPTY_OBJ
}
}
简单封装例子
import { useCssModule, ref, watchEffect } from 'vue'
function useClassnames(namesGetter) {
const $styles = useCssModule()
const classnames = ref([])
watchEffect(function() {
classnames.value = getClassnames()
})
function getClassnames() {
const names = namesGetter()
if (Array.isArray(names)) {
return names.filter(i => !!i).map(it => $styles[it])
} else {
const result = []
for (const key in names) {
names[key] && classNames.push($styles[key])
}
return result
}
}
return classnames
}
// 使用
const rootStyle = useClassnames(() => ({
hello: true,
active: props.active
}))
useCssVars
在 Vue 组件的 root el 的 style 上添加 CSS 变量。
// 用法
// template
<div class="text-color">1</div>
// script
function useTheme() {
const theme = reactive({
textColor: '#b53f6b'
})
const getTheme = (useProxy) => {
const { active } = useProxy
return active ? theme : {}
}
useCssVars(getTheme)
}
export default {
setup() {
useTheme()
const active = ref(true)
return { active }
}
}
// style
.text-color {
color: var(--textColor);
}
useContext
获取当前组件里 setup 方法的第二个参数 context
function useHeaderSlot() {
const { slots } = useContext()
return slots && slots.header
}
export default {
setup() {
const headerSlot = useHeaderSlot()
}
}
拓展
由于Compositon API 已经不存在 this 了。所以获取插件添加到全局的方法比较麻烦。但是可以从组件实例的 proxy 对象里能取到。
// main.js
const app = createApp(App)
app.config.globalProperties.foo = 'bar'
app.mount('#app')
// useRenderContext,js
function useRenderContext(){
const i = getCurrentInstance()!
return i.proxy
}
setup() {
const { foo } = useRenderContext()
foo // bar
}