这是面试的时候遇到的一个面试题,当时没回答上来。。。
var() - CSS:层叠样式表 | MDN
自定义属性(--*):CSS 变量 - CSS:层叠样式表 | MDN
我们先了解一下 css var()函数以及 css 自定义属性
通过 var 函数和自定义属性可以复用某些 css 样式,例如:
:root {
--main-bg-color: pink;
}
body {
background-color: var(--main-bg-color);
}
.text {
background-color: var(--main-bg-color)
}
当然 var()函数是有作用域的,读取顺序 内联自定义属性 => class 自定义属性 => root 自定义属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
:root {
--color: pink;
}
.text {
--color: red;
color: var(--color);
}
</style>
</head>
<body>
<!-- 优先读取内联自定义属性 -->
<div class="text" style="--color: blue">hello</div>
</body>
</html>
那如何在 vue style 标签中使用响应式变量呢?
方法一:v-bind:style + var()
<template>
<div class="text" :style="{ '--color': color }">hello</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const color = ref('red')
onMounted(() => {
setTimeout(() => {
color.value = 'pink'
}, 1000)
})
</script>
<style>
.text {
color: var(--color);
}
</style>
原理:通过绑定元素的 style 创建自定义属性,使用 var()函数访问创建的自定义属性
方法二:通过 v-bind CSS 函数将 CSS 的值链接到变量上,且支持 JavaScript 表达式(需要用引号包裹起来,支持模板字符串)
<template>
<p>hello</p>
</template>
<script setup>
const theme = {
color: 'red'
}
</script>
<style scoped>
p {
color: v-bind('theme.color'); /* 绑定某个变量 */
}
</style>
<template>
<p>hello</p>
</template>
<script setup>
const colorNum = 1
</script>
<style scoped>
p {
color: v-bind('colorNum > 1 ? ' blue': ' pink''); /* 支持JavaScript表达式 */
}
</style>
原理:vue 会将 v-bind 的值编译成哈希化的 CSS 自定义属性,并通过内联的方式应用到组件的根结点上,内部再通过 var() 函数使用(方法二其实就是方法一的语法糖,简化了内部操作)