假如我有一個需求,必須通過 js 執行動畫,還得讓 css 去配合。
拿一個簡單卻不太恰當的例子來說:
opacity
‘一閃一閃’效果的實作。傳統Vue必須要利用“動态
style
”。
<template>
<h1 :style="{opacity: opacity}">Vue</h1>
</template>
<script>
export default {
data () {
return { opacity: 0 }
},
mounted () {
setInterval(() => {
this.opacity >= 1 && (this.opacity = 0)
this.opacity += 0.2
}, 300)
}
}
</script>
<style>
h1 {
color: rgb(65,184,131);
}
</style>
但是在 vue3.2 中,尤大提出了一個概念:Js in Css。它讓我們可以在 css 中使用 js 變量,更好的控制動畫的軌迹!進而達到“js向css傳值”的效果。
使用前需注意:本規則依托于
vite
,除此之外需先引入
vars
:

<template>
<h1>Vue</h1>
</template>
<script>
export default {
data () {
return { opacity: 0 }
},
mounted () {
setInterval(() => {
this.opacity >= 1 && (this.opacity = 0)
this.opacity += 0.2
}, 300)
}
}
</script>
<style vars="{ opacity }"> <!-- 綁定css中接收的變量 -->
h1 {
color: rgb(65,184,131);
opacity: var (--opacity);
}
</style>
那 css 怎麼向 js 傳參?比如“主題跟随系統變化”:
@media (prefers-color-scheme: dark) {
/* 黑暗模式,深色主題 */
}
@media (prefers-color-scheme: light) {
/* 淺色主題 */
}
比如“響應式布局中判斷pc還是移動端”:
@media (any-hover: none) {
/* 裝置不支援hover事件 */
}
等等。
這些情況大多是由于頁面的變化要導緻一些感官(UI)和操作上的改變。而 css 和 js 的“邊界一緻性”無法保證。
拿上面的
any-hover
來說,js 中就沒有支援相關的 API。
除此之外,通常還有人這麼做:
@media screen and (max-width:) {
/* 小螢幕寬度下的響應式布局 */
}
這倒是可以直接在 js 中對
screen.width
進行
if
操作。但是假如一段時間之後,發現這個臨界寬度有問題(比如手機橫屏的時候),這時候但凡少修改一方,就會導緻“bug”的産生。實為不智。
但是我們可以通過
- content僞元素内容傳參
例如:
@media (any-hover: none) {
body::before {
content: 'hoverNone';
display: none;
}
}
此時就可以通過JS代碼擷取body僞元素傳遞的資訊是什麼了:
var strContent = getComputedStyle(document.body, '::before').content;
// strContent結果是'none'則表示支援hover
// strContent結果是'"hoverNone"'則表示不支援hover經過,需要換成click事件
這樣,我們就可以根據
::before
,
::after
僞元素配合
content
屬性,獲知CSS中傳遞的資訊了。
這種傳參方式的優點在于相容性相對較好,但是不足卻也很明顯,那就是我們傳遞的參數值的數量是有限的,如果我們想一次性傳多個值,就有些捉襟見肘,此時可以試試下面這種方法,借助CSS自定義屬性。
- CSS自定義屬性(CSS變量)傳參
還是拿“跟随系統改變主題色”來說,有了CSS自定義屬性(CSS變量),黑暗模式和淺色模式的開發和維護工作就變得相對容易很多。
:root {
--mode: 'unknown';
}
@media (prefers-color-scheme: dark) {
/* 黑暗模式 */
:root {
--mode: 'dark';
--colorLink: #bfdbff;
--colorMark: #cc0000;
--colorText: #ffffff;
--colorLight: #777777;
}
}
@media (prefers-color-scheme: light) {
/* 淺色主題 */
:root {
--mode: 'light';
--colorLink: #34538b;
--colorMark: #cc0000;
--colorText: #000000;
--colorLight: #cccccc;
}
}
var mode = getComputedStyle(document.documentElement).getPropertyValue('--mode').trim();
// mode結果是'"dark"'則表示黑夜主題,深色模式,黑暗風格,護眼模式。