Vue3 JS 與 SCSS 變量相互使用

在開發中會遇到如下需求:

  1. JS 中使用 SCSS 變量。如在 scss 中定義了一個顏色,el-menu 組件使用該顏色作為背景色,此時需要獲取 scss 變量,通過 background-color 屬性將該變量值傳遞給 el-menu 組件(當然你也可以在 JS 中重新定義一個變量存儲該顏色)。
  2. SCSS 中使用 JS 變量。如動態換膚功能,用戶選中某個顏色作為主題色,整個系統的主題色都切換為這個主題色。用戶選擇的這個顏色使用 JS 變量存儲,SCSS 中需要使用該 JS 變量存儲的顏色。類似的場景還有暗黑模式等。

本文提供解決上述問題的思路。

1 JS 使用 SCSS 變量

1.1 創建 SCSS 變量文件

src 目錄下創建 scss 目錄,該目錄存儲 scss 文件。這裡需要注意,如果 JS 要使用 SCSS 文件中定義的變量,在 vue3 中,存儲變量的 SCSS 文件名格式為 xxx.module.scss

variables.module.scss。與 vue 2.x 不同,這裡的 .module 不能省略,在 vue 2.x 不要求文件名使用 xxx.module.scss 的方式。

src/scss/ 目錄下創建

config.module.scss 文件,該文件用於定義 scss 變量:

$titleColor: #FF0000;

1.2 導出 SCSS 變量

上面創建的 config.module.scss 文件中定義了一個變量:$titleColor

如果咱們只是在其他 scss 文件或 vue 文件的 style 標籤中使用,只需要在對應文件使用 @import 引入 config.module.scss 即可。但如果需要在 script 中的 JS/TS 中使用,還需要通過 export 將需要使用的變量導出:

$titleColor: #FF0000;

:export {
  titleColor: $titleColor;
}

這樣便將 $titleColor 的值通過變量名 titleColor 導出給 JS/TS。

1.3 使用 SCSS 變量

在 vue 文件的 script 中如果要使用上面的變量,先導入該 scss 文件:

import config from '@/scss/config.module.scss'

config 的值就是 scss 文件 :export 的對象。輸出 config 對象:

console.log(config)

控制台輸出:

{titleColor: '#FF0000'}

此時便可通過 config.titleColor 獲取 scss 文件中 $titleColor 的值。

vue 代碼如下:

<template>
  <div>
    <h1 :style="{color: color}">JS 獲取 SCSS 變量值</h1>
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import config from '@/scss/config.module.scss'

const color = ref(config.titleColor)
</script>

2 CSS 變量

在討論 SCSS 代碼使用 JS 變量前,咱需要先聊聊 CSS Next 中的 CSS 變量。CSS 2、CSS 3 大部分哥們都耳熟能詳,CSS Next 也不是什麼新鮮事物了。其中 CSS Next 很厲害的一個能力就是 CSS 變量。

2.1 全局 CSS 變量

咱可以在上面的 src/scss 目錄下創建 test.css 文件來嘗試使用 css 變量。

:root {
  --bgColor: pink;
}

body {
  background-color: var(--bgColor);
}

:root 中定義了全局 CSS 變量,CSS變量的命名約定以兩個 – 開頭,上面定義了一個全局 CSS 變量,變量名為 –bgColor

使用變量時使用 CSS 的 var() 函數。

main.ts 中引入該文件:

import '@/scss/test.css'

此時在瀏覽器中可以看到背景色變成粉紅色。

2.2 組件內 CSS 變量

在組件中也可以使用 CSS 變量。在對應的選擇器中定義變量即可。

<template>
  <div class="demo">
    <div class="css-div">CSS 變量</div>
  </div>
</template>

<script lang="ts" setup>
</script>

<style scoped lang="scss">
.demo {
  --font-size: 30px;

  .css-div {
    --textColor: blue;

    font-size: var(--font-size);
    color: var(--textColor);
  }
}
</style>

有了 CSS 變量的基礎,接下來就可以討論 scss 中如何使用 JS 變量了。

3 SCSS 使用 JS 變量

咱們用一個 demo 來說明 scss 中如何使用 js 變量:有三個按鈕和一個 div,點擊三個按鈕會切換 div 的背景色和文字顏色。

3.1 基礎代碼

首先實現頁面的基礎代碼:

<template>
  <div class="demo">
    <button v-for="(item, index) in btns"
            :key="index"
            @click="onBtnClick(item.bgColor, item.textColor)"
    >{{ item.title }}</button>

    <div>
      <div class="example">Hello World</div>
    </div>
  </div>
</template>

<script lang="ts" setup>
const btns = [
  { title: '紅色主題', bgColor: '#FF9191', textColor: '#FF0000' },
  { title: '藍色主題', bgColor: '#B3C4FF', textColor: '#042BA9' },
  { title: '默認主題', bgColor: '#333333', textColor: '#FFFFFF' }
]
const onBtnClick = (bgColor: string, textColor: string) => {
  console.log(bgColor, textColor)
}
</script>

<style scoped lang="scss">
.demo {
  padding: 10px;

  .example {
    --textColor: #FFFFFF;
    --bgColor: #333333;

    display: inline-block;
    margin-top: 20px;
    font-size: 20px;
    padding: 20px 50px;
    color: var(--textColor);
    background: var(--bgColor);
  }
}
</style>

頁面如下:

image-20221016172352073

上面代碼比較簡單,btns 變量定義了三個按鈕,通過 v-for 顯示三個按鈕。點擊按鈕的時候傳遞 bgColortextColor 兩個參數給點擊事件 onBtnClick 函數。顯示 Hello World 的 div,通過 –textColor–bgColor 兩個變量來控制背景色和文字顏色。

接下來便是實現點擊不同按鈕時,使用不同的文字顏色和背景色。

Vue3 中提供了兩種方式來實現動態改變 css 變量。下面兩種方式都基於上面的基礎代碼實現:

3.2 方式1:setProperty

Vue 提供了 setProperty 的方式來改變 CSS 變量。

  1. 為目標 div 添加 ref 屬性:
<template>
		...
    <div>
      <div class="example" ref="exampleRef">Hello World</div>
    </div>
  </div>
</template>
  1. 獲取到該 div 的引用(ref):
import { ref } from 'vue'

const exampleRef = ref<HTMLDivElement | null>()
...
  1. 調用該引用 style 屬性的 setProperty 方法:
<script lang="ts" setup>
...
const onBtnClick = (bgColor: string, textColor: string) => {
  if (exampleRef.value) {
    exampleRef.value?.style.setProperty('--textColor', textColor)
    exampleRef.value?.style.setProperty('--bgColor', bgColor)
  }
}
</script>
...

3.3 方式2:v-bind

Vue3 中為 vue 文件的 style 提供了 v-bind 函數,實現了將 JS/TS 變量綁定到 CSS 變量上。

  1. 在 TS 中定義兩個變量存儲點擊事件時傳遞的兩個參數:
const currentBgColor = ref('#333333')
const currentTextColor = ref('#FFFFFF')
  1. 點擊事件中點參數賦值給上面兩個變量:
const onBtnClick = (bgColor: string, textColor: string) => {
  currentBgColor.value = bgColor
  currentTextColor.value = textColor
}
  1. style 中使用 v-bind 綁定上面兩個 JS 變量:
.demo {
	...

  .example {
    --textColor: v-bind(currentTextColor);
    --bgColor: v-bind(currentBgColor);

    ...
    color: var(--textColor);
    background: var(--bgColor);
  }
}

上面兩種方式根據自己的喜好使用。大家可以根據上面的思路嘗試實現主題切換、動態換膚等功能,在後面的實戰系列文章中咱在繼續討論這個話題。

感謝你閱讀本文,如果本文給了你一點點幫助或者啟發,還請三連支持一下,點贊、關注、收藏,作者會持續與大家分享更多乾貨

Tags: