当前位置: 首页 > news >正文

【前端小点】vue3项目内根据主题读取不同文件夹下的图片资源(图片文件)

项目要求实现一键换肤的功能,不仅仅是主题颜色上的替换,还有图片素材的替换,主题颜色替换的方案大同小异,下面仅对图片素材的一件替换进行方法描述。

主要思路

使用本地仓库对当前主题进行存储,系统根据主题去加载不同文件夹下的素材文件。

实现方式

1、动态读取文件夹下的图片文件。

注意:不同的素材我们用的是不同文件夹,但是文件名字是一样的,存储位置也是相对统一的,如下图所示。例如:暗色主题下有一个图片地址为bg.jpg,则亮色主题下也需要有一个图片地址为bg.jpg
在这里插入图片描述
编写js/ts对文件内容进行读取并存储,我的文件位置: src/themes.js
注意: import.meta.glob必须是静态字符串,不可设置为动态获取的.

themes.js
// 获取文件夹下所有文件
const images = import.meta.glob(`./assets/themes/light/**/**/*.*`)
const commonImages = import.meta.glob(`./assets/themes/common/**/**/*.*`)

let prefix = './assets/themes/light/'
let commonPrefix = './assets/themes/common/'

/**
 *
 * @param {*} imagePaths
 * @returns
 */
const handleFileName = (imagePaths, pathPrefix) => {
  console.log(imagePaths)
  let pathObj = {}
  Object.keys(imagePaths).forEach((key) => {
    key = key.replace(pathPrefix, '')
    let pathArr = key.split('/')
    let length = pathArr.length
    // 名字
    let name = pathArr[length - 1]
    // 文件夹
    let folder = ''
    if (length >= 2) {
      folder = pathArr[length - 2]
    }
    // 父文件夹
    let folderParent = ''
    if (length >= 3) {
      folderParent = pathArr[length - 3]
    }
    pathObj[key] = {
      name,
      folder,
      folderParent
    }
  })
  return pathObj
}


// 获取文件名和文件夹名
let files = handleFileName(images, prefix)
console.log(files)
let commonFiles = handleFileName(commonImages, commonPrefix)

const themes = {
  light: {},
  dark: {},
  common: {}
}

// 设置不同主题下的图片 文件夹/文件
Object.keys(files).forEach((key) => {
  let fileObj = files[key]
  let { name, folder, folderParent } = fileObj
  let lightHref = new URL(`./assets/themes/light/${key}`, import.meta.url).href
  let darkHref = new URL(`./assets/themes/dark/${key}`, import.meta.url).href
  if (folderParent) {
    themes.light[folderParent] ? {} : themes.light[folderParent] = {}
    themes.light[folderParent][folder] ? {} :themes.light[folderParent][folder]
    themes.light[folderParent][folder][name] = lightHref
    themes.dark[folderParent] ? {} : themes.dark[folderParent] = {}
    themes.dark[folderParent][folder] ? {} : themes.dark[folderParent] = {}
    themes.dark[folderParent][folder][name] = darkHref
  } else if (folder) {
    themes.light[folder] ? {} : themes.light[folder] = {}
    themes.light[folder][name] = lightHref
    themes.dark[folder] ? {} : themes.dark[folder] = {}
    themes.dark[folder][name] = darkHref
  } else {
    themes.light[name] = lightHref
    themes.dark[name] = darkHref
  }
})

// 设置公共图片文件
Object.keys(commonFiles).forEach((key) => {
  let fileObj = commonFiles[key]
  let { name, folder, folderParent } = fileObj
  let commonHref = new URL(`./assets/themes/common/${key}`, import.meta.url).href
  if (folderParent) {
    themes.common[folderParent] ? {} : themes.common[folderParent] = {}
    themes.common[folderParent][folder] = {}
    themes.common[folderParent][folder][name] = commonHref
  } else if (folder) {
    themes.common[folder] ? {} : themes.common[folder] = {}
    themes.common[folder][name] = commonHref
  } else {
    themes.common[name] = commonHref
  }
})

export default themes

2、对项目内的主题(暗色\亮色)进行仓库存储

这里我使用的是pinia进行本地数据存储,我的文件位置src/pinia/modules/theme.ts

import { defineStore } from 'pinia'
import { ref } from 'vue'
import themesImage from '@/themes'

const useThemeStore = defineStore('themeStore', () => {
  let theme = ref('light')
  const toggleTheme = () => {
    theme.value = theme.value === 'light' ? 'dark' : 'light'
  }
  const getThemeImage = (imgPath: string) => {
    return getImage(theme.value, imgPath)
  }
  const getCommonImage = (imgPath: string) => {
    return getImage('common', imgPath)
  }
  const getImage = (themeName: string, imgPath: string) => {
    let imagePath = imgPath.split('/')
    imagePath.length
    if (imagePath.length == 1) {
      return themesImage[themeName][imagePath[0]]
    } else if (imagePath.length == 2) {
      return themesImage[themeName][imagePath[0]][imagePath[1]]
    } else {
      return themesImage[themeName][imagePath[0]][imagePath[1]][imagePath[2]]
    }
  }
  return {
    theme,
    toggleTheme,
    getThemeImage,
    getCommonImage
  }
})

export default useThemeStore

3、编写工具类获取图片地址

编写工具类,便于后续界面读取文件,我的文件地址为: src/utils/themes.ts

import useThemeStore from '@/pinia/modules/theme'
const themeStore = useThemeStore()

// 获取主题图片
export const getThemeImage = themeStore.getThemeImage
// 获取公共图片
export const getCommonImage = themeStore.getCommonImage

4、在vue组件中使用

做好准备工作以后,我们只需在组件中引入我们的工具类即可。

<template>
	<div class="container">
		<img :src="themeUtils.getThemeImage('index/logo.png')" alt="" class="img" />
	    <img :src="themeUtils.getCommonImage('logo.png')" alt="" class="img" />
	    <el-button @click="themeUtils.toggleTheme">一键换肤</el-button>
	</div>
</template>

<script lang="ts" setup>
import * as themeUtils from '@/utils/themes'
</script>

<style lang="scss" scoped>
.img{
  border: 1px solid #ccc;
  border-radius: 10px;
  margin-right: 10px;
}
.container{
  display: flex;
  align-items: center;
}
</style>

效果如下:
在这里插入图片描述
点击一键换肤以后
在这里插入图片描述

相关文章:

  • 重磅来袭————YOLOv12:Attention-Centric Real-Time Object Detectors
  • AIGC视频生成明星——Emu Video模型
  • 5-循环语句
  • 【Linux-网络】初识计算机网络 Socket套接字 TCP/UDP协议(包含Socket编程实战)
  • 推荐系统-排序模型
  • 力扣-回溯-17 电话号码的字母组合
  • C++ 课程设计 汇总(含源码)
  • B+树作为数据库索引结构的优势对比
  • HC32F460_GPIO驱动库
  • 阿里云SLB负载均衡的ALB和NLB有啥区别?一个是7层一个是4层
  • Redis中哈希(Hash)常见命令详解
  • 快速入门Springboot+vue——MybatisPlus多表查询及分页查询
  • 第四章:高级特性与最佳实践 - 第四节 - Tailwind CSS CSS 提取和打包优化
  • [NKU]C++理论课 cours 3 数据抽象(封装->隐藏实现的手段,隐藏->封装的重要目标)
  • 跳格子游戏
  • Sun-Panel:简洁且美观的导航首页开源项目!!
  • LeetCode 2595.奇偶位数:位运算
  • DeepSeek全系列全平台部署(可代部署)
  • 2025鸿蒙开发面试题汇总——通俗易懂
  • DeepSeek-R1本地部署简易教程
  • 长沙企业做网站/百度电话怎么转人工
  • 西安做网站多钱/免费舆情网站下载大全最新版
  • 电商网站建设合同/推广软件
  • 做网站文字大小/理发美发培训学校
  • 音乐网站开发文档/营销型网站分为哪几种
  • 北京哪家做网站优化/爱站网络挖掘词