Vue3 JS 與 SCSS 變數相互使用

2022-10-17 18:00:37

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

  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);
  }
}

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

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