【前端小点】vue3项目内根据主题读取不同文件夹下的图片资源(图片文件)
- 其他
- 2025-08-24 08:24:02

项目要求实现一键换肤的功能,不仅仅是主题颜色上的替换,还有图片素材的替换,主题颜色替换的方案大同小异,下面仅对图片素材的一件替换进行方法描述。
主要思路使用本地仓库对当前主题进行存储,系统根据主题去加载不同文件夹下的素材文件。
实现方式 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 mon[folderParent] ? {} : themes mon[folderParent] = {} themes mon[folderParent][folder] = {} themes mon[folderParent][folder][name] = commonHref } else if (folder) { themes mon[folder] ? {} : themes mon[folder] = {} themes mon[folder][name] = commonHref } else { themes mon[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>效果如下: 点击一键换肤以后
【前端小点】vue3项目内根据主题读取不同文件夹下的图片资源(图片文件)由讯客互联其他栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“【前端小点】vue3项目内根据主题读取不同文件夹下的图片资源(图片文件)”