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: