Vue3 中如何优雅地使用 JSON 文件
在 Vue3 项目开发中,JSON 文件常用于存储静态配置、多语言文本、模拟数据或结构化信息,本文将详细介绍在 Vue3 中使用 JSON 文件的多种方式,包括直接导入、动态加载、结合 Pinia 状态管理以及处理跨域请求等场景,帮助开发者根据实际需求选择最合适的方案。
直接导入 JSON 文件(静态数据)
对于不会频繁变动的静态数据(如默认配置、固定枚举值、模拟响应数据等),Vue3 支持直接通过 ES6 模块语法导入 JSON 文件,这是最简单直接的方式。
准备 JSON 文件
在 src 目录下创建 data 文件夹(或其他自定义目录),存放 JSON 文件,src/data/config.json:
{
"appName": "Vue3 Demo",
"version": "1.0.0",
"theme": "light",
"features": ["auth", "dashboard", "settings"]
}
在组件中直接导入
在 Vue3 组件(或 Composition API 的 setup 函数)中,通过 import 语法直接引入 JSON 文件,Vue3 会自动将其解析为 JavaScript 对象:
<template>
<div>
<h1>{{ config.appName }}</h1>
<p>Version: {{ config.version }}</p>
<p>Theme: {{ config.theme }}</p>
<ul>
<li v-for="feature in config.features" :key="feature">{{ feature }}</li>
</ul>
</div>
</template>
<script setup>
import config from '@/data/config.json'
// 直接使用导入的 JSON 数据
console.log(config.appName) // 输出: Vue3 Demo
</script>
注意事项
- 路径别名:推荐使用 指向
src目录(需在vite.config.js或vue.config.js中配置),避免相对路径混乱。 - 类型支持:如果使用 TypeScript,需安装
@types/json5(或通过tsconfig.json配置resolveJsonModule),否则可能提示类型错误。
动态加载 JSON 文件(按需加载)
当 JSON 文件较大或需要按需加载(例如根据用户操作、路由切换动态加载数据)时,可以使用 fetch 或 axios 动态请求 JSON 文件,避免一次性加载所有数据。
使用 fetch 动态加载
fetch 是浏览器内置的 API,无需额外安装,适合简单的动态请求:
<template>
<div>
<button @click="loadJsonData">加载数据</button>
<div v-if="jsonData">
<h2>{{ jsonData.title }}</h2>
<p>{{ jsonData.content }}</p>
</div>
<p v-else>加载中...</p>
</div>
</template>
<script setup>
import { ref } from 'vue'
const jsonData = ref(null)
const loadJsonData = async () => {
try {
const response = await fetch('/api/data/dynamic.json') // JSON 文件路径(需确保服务器可访问)
if (!response.ok) throw new Error('加载失败')
jsonData.value = await response.json()
console.log(jsonData.value)
} catch (error) {
console.error('动态加载 JSON 失败:', error)
}
}
</script>
使用 axios 动态加载
axios 是流行的 HTTP 请求库,支持请求拦截、错误处理等功能,适合复杂项目:
# 安装 axios npm install axios
<template>
<div>
<button @click="loadJsonData">加载数据</button>
<div v-if="jsonData">
<h2>{{ jsonData.title }}</h2>
<p>{{ jsonData.content }}</p>
</div>
<p v-else>加载中...</p>
</div>
</template>
<script setup>
import { ref } from 'vue'
import axios from 'axios'
const jsonData = ref(null)
const loadJsonData = async () => {
try {
const response = await axios.get('/api/data/dynamic.json')
jsonData.value = response.data
console.log(jsonData.value)
} catch (error) {
console.error('动态加载 JSON 失败:', error)
}
}
</script>
注意事项
- 开发环境:JSON 文件存放在
public目录下,可通过/api/data/dynamic.json直接访问(public目录下的文件会直接作为静态资源)。 - 生产环境:确保 JSON 文件的路径可访问,或通过后端 API 返回 JSON 数据(避免跨域问题)。
结合 Pinia 管理全局 JSON 数据
JSON 数据需要在多个组件间共享(如全局配置、用户权限数据等),可以使用 Pinia(Vue3 官方推荐的状态管理库)存储和管理数据。
安装 Pinia
npm install pinia
创建 Store 并加载 JSON 数据
在 src/stores 目录下创建 configStore.js:
import { defineStore } from 'pinia'
import config from '@/data/config.json' // 直接导入静态 JSON
export const useConfigStore = defineStore('config', {
state: () => ({
appConfig: config,
loading: false
}),
actions: {
async loadDynamicConfig() {
this.loading = true
try {
const response = await fetch('/api/data/dynamic.json')
const data = await response.json()
this.appConfig = { ...this.appConfig, ...data } // 合并静态和动态数据
} catch (error) {
console.error('加载动态配置失败:', error)
} finally {
this.loading = false
}
}
}
})
在组件中使用 Store
<template>
<div>
<h1>{{ configStore.appConfig.appName }}</h1>
<p>Theme: {{ configStore.appConfig.theme }}</p>
<button @click="configStore.loadDynamicConfig">加载动态配置</button>
<p v-if="configStore.loading">加载中...</p>
</div>
</template>
<script setup>
import { useConfigStore } from '@/stores/configStore'
const configStore = useConfigStore()
</script>
优势
- 全局共享:避免重复请求,数据一致性更高。
- 响应式:Pinia 状态自动响应式,修改数据后组件会自动更新。
- 可扩展:支持异步加载、数据合并、持久化(如结合
pinia-plugin-persistedstate)。
处理跨域请求(JSON 文件在远程服务器)
JSON 文件存放在远程服务器(如 CDN、其他域名的 API),可能会遇到跨域问题(CORS),以下是解决方案:
服务器端配置 CORS
要求远程服务器在响应头中添加 Access-Control-Allow-Origin 字段,
Access-Control-Allow-Origin: * # 允许所有域名(不安全,建议指定具体域名) Access-Control-Allow-Origin: https://your-vue3-app.com # 仅允许你的域名
使用代理(开发环境)
在 vite.config.js(Vite 项目)或 vue.config.js(Vue CLI 项目)中配置代理,将请求转发到目标服务器,避免跨域:
// vite.config.js
export default {
server: {
proxy: {
'/api': {
target: 'https://remote-server.com', // 目标服务器
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '') // 可选:重写路径
}
}
}
}
然后在代码中通过代理路径请求:
const response = await fetch('/api/data.json') // 实际请求 https://remote-server.com/data.json
使用 JSONP(仅限 GET 请求)
如果服务器不支持 CORS 且无法修改,且请求是 GET 方法,可以使用 JSONP(但需服务器支持回调),JSONP 已逐渐被淘汰,建议优先使用 CORS 或代理。
最佳实践总结
| 场景 | 推荐方案 | 优点 | 缺点 |
|---|---|---|---|
| 静态数据(配置、枚举) | 直接导入 JSON 文件 | 简单、无需请求、性能高 | 数据无法动态更新 |
| 按需加载(大数据、用户操作) | fetch/axios 动态请求 |
按需加载、支持动态更新 | 需处理异步和错误 |
| 全局共享数据 | Pinia + JSON(静态或动态加载) | 响应式、全局共享、可扩展 |



还没有评论,来说两句吧...