让我为您详细讲解一下“Vue3 style CSS 变量注入的实现”的完整攻略。
什么是 Vue3 style CSS 变量注入
在 Vue3 中,我们可以利用 CSS 变量注入 的方式来为组件注入样式,本质上就是通过 Vue3 提供的 $attrs
和 style
属性处理方式,将常量化的 CSS 变量写入到 Vue3 的虚拟 DOM 中。
这种方式比起之前 Vue2 中使用 Style-Scoped 等形式,更加灵活、可控,且本质上只是利用的 CSS 变量做一个常量注入,所以效率方面比起其他形式更高。
Vue3 style CSS 变量注入的实现
Vue3 注入样式采用的是 Vue3 自己的解决方案,思路是通过 $attrs
将外部传入的样式集合加入 style,在组件内部的 html 标签上,再通过 style
的方式,将 $attrs
里的值注入到组件中。
具体实现方式如下:
第一步:为样式集合起一个别名
我们在组件中定义一个别名,用于引用组件所需的样式。例如,这里我们定义了一个别名 cssVars
:
const cssVars = {
'--primary-color': '#1A1A1E',
'--bg-color': '#EFEFEF',
'--text-color': '#1A1A1E',
'--btn-bg-color': '#3B385F',
'--btn-text-color': '#FFFFFF',
'--radius': '5px'
}
这里的 cssVars
就是一个常量化的 CSS 变量集合,我们可以将这些变量注入到组件中。
第二步:创建组件
在组件定义的时候,我们需要以下两步:
- 在
setup()
函数内,使用inject
方法将外部传入的样式与组件进行关联:const cssVars = inject('cssVars')
- 在组件 template 内,通过
$attrs
和style
将内部样式和外部样式合并
具体代码如下:
<template>
<div :style="computedStyle" v-bind="$attrs">
<slot></slot>
</div>
</template>
<script>
export default {
setup(props, { attrs }) {
// 使用 inject 方法将外部传入的样式与组件进行关联
const cssVars = inject('cssVars')
return { cssVars }
},
computed: {
// 转换为字典的 style 样式
computedStyle() {
return Object.entries(this.cssVars).reduce(
(styleStr, [key, val]) => `${styleStr}${key}:${val};`,
''
)
}
}
}
</script>
以上代码中,inject
方法将外部传入的样式与组件进行关联,返回值 cssVars
就是传入的样式集合,然后通过 computed
计算属性,将这些样式化为 css 样式字符串。
第三步:使用组件
在上述步骤完成之后,我们就可以开始使用这个组件了。在使用时,需要如下操作:
- 在父组件中以一个 prop 的形式传入样式集合:
<component :css-vars="cssVars"></component>
- 在父组件的
provide
中传入样式集合对象provide('cssVars', this.cssVars)
下面给出一个示例:
<template>
<div>
<style-component :cssVars="cssVars">
<div class="content">这是一个使用 css 变量的组件</div>
</style-component>
</div>
</template>
<script>
import StyleComponent from './StyleComponent'
export default {
components: { StyleComponent },
data() {
return {
cssVars: {
'--text-color': 'red',
'--font-size': '24px'
}
}
},
provide() {
return {
cssVars: this.cssVars
}
}
}
</script>
这个例子中,我们将一个名为 cssVars
的变量传入到子组件 StyleComponent
中,并使用 provide
将其传递给子组件。这样,子组件就可以根据提供的样式集合,注入到组件样式中。
示例说明
示例一:主题切换
假设我们有一个需求,可以在整个 Vue3 项目中实现主题切换。这里我们假设有两个主题:明亮和暗黑主题,每个主题都包含了常用的 CSS 变量设置。当用户选择主题时,应该将对应主题的 CSS 变量应用到整个项目中。
首先,我们需要在项目中定义两个常量化的 CSS 变量文件:
// light-theme.css.js
export const cssVars = {
'--primary-color': '#1A1A1E',
'--bg-color': '#EFEFEF',
'--text-color': '#1A1A1E',
'--btn-bg-color': '#3B385F',
'--btn-text-color': '#FFFFFF',
'--radius': '5px'
}
// dark-theme.css.js
export const cssVars = {
'--primary-color': '#495057',
'--bg-color': '#212529',
'--text-color': '#F8F9FA',
'--btn-bg-color': '#0D6EFD',
'--btn-text-color': '#FFFFFF',
'--radius': '5px'
}
然后,我们需要在项目中创建一个可以进行主题切换的工具类。这个类可以对当前全局应用的样式进行修改:
// theme.js
// 引入两个样式集合
import { cssVars as lightCssVars } from './light-theme.css.js'
import { cssVars as darkCssVars } from './dark-theme.css.js'
export default class Theme {
static THEME_MAP = {
light: lightCssVars,
dark: darkCssVars
}
static setTheme(theme) {
document.documentElement.style.cssText = Object.entries(
this.THEME_MAP[theme]
).reduce(
(acc, [key, value]) => {
return `${acc} ${key}:${value};`
},
''
)
}
}
这个类中,我们引入了之前定义的两个样式集合,然后定义了一个 setTheme
方法。这个方法接受一个主题值作为参数,然后将对应主题的 CSS 变量应用到全局。
最后,在 Vue3 项目中我们需要做两件事情:
- 在 App.vue 中引入 Theme 类,并在 mounted 钩子中设置主题;
- 在任何一个页面中,通过 provide 函数将主题样式传入到子组件:
<template>
<div>
<style-component :cssVars="cssVars">
<div class="content">这是一个使用 css 变量的组件</div>
</style-component>
</div>
</template>
<script>
import StyleComponent from './StyleComponent'
import { cssVars } from '../light-theme.css.js'
import { mapGetters } from 'vuex'
export default {
components: { StyleComponent },
provide() {
return {
cssVars
}
}
}
</script>
在这个例子中,我们将引入的 light-theme.css.js
的样式集合传入到了子组件当中。
示例二:动态修改单个变量
有时候,我们需要在组件中动态修改单个变量,这个时候可以借助 Vue3 的响应式系统,并结合 $attrs
和 style
来实现。
<template>
<div>
<style-component :cssVars="cssVars">
<button :style="buttonStyle" @click="toggleColor">Toggle Color</button>
</style-component>
</div>
</template>
<script>
import StyleComponent from './StyleComponent'
export default {
components: { StyleComponent },
data() {
return {
color: '#000000'
}
},
computed: {
buttonStyle() {
return {
backgroundColor: this.color
}
}
},
methods: {
toggleColor() {
this.color = this.color === '#000000' ? '#FF0000' : '#000000'
}
},
provide() {
return {
cssVars: {}
}
}
}
</script>
在这个例子中,我们使用 color
来表示当前颜色值,然后通过 computed
属性将这个值转换为按钮背景色,最后将这个样式注入到了模板中。当用户点击按钮时,通过 toggleColor 方法可对颜色值进行修改,此时 Vue3 的响应式系统会负责自动更新页面上的颜色值。
总结
Vue3 的 CSS 变量注入是一个非常灵活的方案,可以用于实现各种需求。其中,主题切换和动态修改单个 CSS 变量是两个比较常见的用例。在实现这些用例时,我们需要将组件内部的样式集合和外部传入的样式集合进行合并,然后通过 $attrs
和 style
将样式值注入到组件中。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Vue3 style CSS 变量注入的实现 - Python技术站