如何使用 vite 动态导入 json 文件
how to import a json file using vite dynamicly
我正在使用 vue-i18n in a Nuxtjs 项目,我想用 vite 动态导入我的语言环境文件。
当我使用webpack时,那些代码运行很好
plugins/i18n.js
import Vue from 'vue';
import VueI18n from 'vue-i18n';
import config from '@/config';
Vue.use(VueI18n);
let messages = Object;
config.locale.available.forEach(locale => {
messages[locale] = require(`~/locales/${locale}.json`);
});
export default ({ app, store }) => {
app.i18n = new VueI18n({
locale: store.state.locale.locale,
messages: messages
});
}
我知道vitejs没有require()
,也是vitejs的glob-import特性
- 所以我首先尝试如下:
let messages = Object,
languages = import.meta.glob('../locales/*.json'); // => languages = {} (languages only get {} value)
config.locale.available.forEach(locale => {
messages[locale] = languages[`../locales/${locale}.json`];
});
但是 languages
只得到了 {}
值。
- 然后我尝试使用
import()
let messages = Object,
translate = lang => () => import(`@/locales/${lang}.json`).then(i => i.default || i);
config.locale.available.forEach(locale => {
messages[locale] = translate(locale);
});
终端和控制台都没有错误,但是没有正确加载语言环境文件。
只有我一一import()
问题才会消失:
import en from '@/locales/en.json';
import fr from '@/locales/fr.json';
import ja from '@/locales/ja.json';
let messages = Object;
messages['en'] = en;
messages['fr'] = fr;
messages['ja'] = ja;
CodeSandbox
但是,如何动态导入呢?
我用谷歌搜索了一下,但帮助不大。非常感谢任何人的帮助!
所以,我想我基于 @LiuQixuan's answer on GitHub.
找到了一些东西
//Importing your data
const data = import.meta.glob('../locales/*.json')
//Ref helps with promises I think. I'm sure there are more elegant ways.
const imp = ref([{}])
// From https://github.com/vitejs/vite/issues/77
// by LiuQixuan commented on Jun 20
for (const path in data) {
data[path]().then((mod) => {
imp.value.push(mod)
})
}
从那里开始,我遍历了 imp.values
,然后我可以循环调用每个文件,通过以下方式获取数据:
JSON.parse(JSON.stringify(**Your data**))
我的 Vue 示例 HTML 是这样的:
<div v-for="(module,i) in imp" :key="i">
<div v-for="(data,j) in module" :key="j">
//at this point you can read it fully with {{ data }}
<div v-for="(jsonText, k) in JSON.parse(JSON.stringify(data))" :key=k">
{{ jsonText.text }}
<div v-for="insideJson in jsonText" :key="insideJson">
{{ insideJson.yourtext }}
</div>
</div>
</div>
</div>
这样,我就可以访问文件中的每个对象。我认为你还有其他需求,但这证明你可以访问每个文件而无需独立导入。
我知道这有点粗糙。我使用了 Stringify 解析,因为数据总是像从不返回,所以我无法直接访问。我确定有更优雅的解决方案,但这是我想出来的。
我本来是想动态导入图片的,弄明白了,然后把方法应用到你的问题上。
对于任何想从文件夹导入动态多图像的人,请使用:
new URL(*, import.meta.url)
如前所述,但增加了:
for (const path in modules) {
modules[path]().then(() => {
//*************
const imgURL = new URL(path, import.meta.url)
//*************
gallery.value.push(imgURL)
})
}
//Then reference that gallery.value in your :src
基于@Lucas Dawson的回答
对于那些必须 运行 在 vite 和 webpack 上编写代码的人
plugins/i18n.js
import Vue from 'vue';
import VueI18n from 'vue-i18n';
Vue.use(VueI18n);
/***
make sure your public config has `VITE_` prefix or it can't be seen in the client side
https://vitejs.dev/guide/env-and-mode.html#env-files
***/
let messages = Object,
locales = process.env.VITE_AVAILABLE_LOCALES.split(',');
// check is using vite or webpack
if (typeof __webpack_require__ !== 'function') {
// for vite
/***
glob and globEager are both work for this
https://vitejs.dev/guide/features.html#glob-import
the differences is
`glob` will return a dynamic import function (lazy load)
`globEager` will return the data of the file from the path directly
if you use `glob`, don't forget `JSON.parse(JSON.stringify(**Your data**))`
if you have trouble with this, use `globEager` may save your day
***/
let modules = import.meta.globEager('/lang/*.json');
locales.forEach(locale => {
messages[locale] = modules[`/lang/${locale}.json`];
});
}
else {
// for webpack (storybook)
locales.forEach(locale => {
messages[locale] = require(`~/lang/${locale}.json`);
});
}
export default ({ app, store }) => {
app.i18n = new VueI18n({
locale: store.getters['locale/locale'],
messages
});
}
再次感谢@Lucas Dawson的回答!
我正在使用 vue-i18n in a Nuxtjs 项目,我想用 vite 动态导入我的语言环境文件。
当我使用webpack时,那些代码运行很好
plugins/i18n.js
import Vue from 'vue';
import VueI18n from 'vue-i18n';
import config from '@/config';
Vue.use(VueI18n);
let messages = Object;
config.locale.available.forEach(locale => {
messages[locale] = require(`~/locales/${locale}.json`);
});
export default ({ app, store }) => {
app.i18n = new VueI18n({
locale: store.state.locale.locale,
messages: messages
});
}
我知道vitejs没有require()
,也是vitejs的glob-import特性
- 所以我首先尝试如下:
let messages = Object,
languages = import.meta.glob('../locales/*.json'); // => languages = {} (languages only get {} value)
config.locale.available.forEach(locale => {
messages[locale] = languages[`../locales/${locale}.json`];
});
但是 languages
只得到了 {}
值。
- 然后我尝试使用
import()
let messages = Object,
translate = lang => () => import(`@/locales/${lang}.json`).then(i => i.default || i);
config.locale.available.forEach(locale => {
messages[locale] = translate(locale);
});
终端和控制台都没有错误,但是没有正确加载语言环境文件。
只有我一一import()
问题才会消失:
import en from '@/locales/en.json';
import fr from '@/locales/fr.json';
import ja from '@/locales/ja.json';
let messages = Object;
messages['en'] = en;
messages['fr'] = fr;
messages['ja'] = ja;
CodeSandbox
但是,如何动态导入呢?
我用谷歌搜索了一下,但帮助不大。非常感谢任何人的帮助!
所以,我想我基于 @LiuQixuan's answer on GitHub.
找到了一些东西//Importing your data
const data = import.meta.glob('../locales/*.json')
//Ref helps with promises I think. I'm sure there are more elegant ways.
const imp = ref([{}])
// From https://github.com/vitejs/vite/issues/77
// by LiuQixuan commented on Jun 20
for (const path in data) {
data[path]().then((mod) => {
imp.value.push(mod)
})
}
从那里开始,我遍历了 imp.values
,然后我可以循环调用每个文件,通过以下方式获取数据:
JSON.parse(JSON.stringify(**Your data**))
我的 Vue 示例 HTML 是这样的:
<div v-for="(module,i) in imp" :key="i">
<div v-for="(data,j) in module" :key="j">
//at this point you can read it fully with {{ data }}
<div v-for="(jsonText, k) in JSON.parse(JSON.stringify(data))" :key=k">
{{ jsonText.text }}
<div v-for="insideJson in jsonText" :key="insideJson">
{{ insideJson.yourtext }}
</div>
</div>
</div>
</div>
这样,我就可以访问文件中的每个对象。我认为你还有其他需求,但这证明你可以访问每个文件而无需独立导入。
我知道这有点粗糙。我使用了 Stringify 解析,因为数据总是像从不返回,所以我无法直接访问。我确定有更优雅的解决方案,但这是我想出来的。
我本来是想动态导入图片的,弄明白了,然后把方法应用到你的问题上。
对于任何想从文件夹导入动态多图像的人,请使用:
new URL(*, import.meta.url)
如前所述,但增加了:
for (const path in modules) {
modules[path]().then(() => {
//*************
const imgURL = new URL(path, import.meta.url)
//*************
gallery.value.push(imgURL)
})
}
//Then reference that gallery.value in your :src
基于@Lucas Dawson的回答
对于那些必须 运行 在 vite 和 webpack 上编写代码的人
plugins/i18n.js
import Vue from 'vue';
import VueI18n from 'vue-i18n';
Vue.use(VueI18n);
/***
make sure your public config has `VITE_` prefix or it can't be seen in the client side
https://vitejs.dev/guide/env-and-mode.html#env-files
***/
let messages = Object,
locales = process.env.VITE_AVAILABLE_LOCALES.split(',');
// check is using vite or webpack
if (typeof __webpack_require__ !== 'function') {
// for vite
/***
glob and globEager are both work for this
https://vitejs.dev/guide/features.html#glob-import
the differences is
`glob` will return a dynamic import function (lazy load)
`globEager` will return the data of the file from the path directly
if you use `glob`, don't forget `JSON.parse(JSON.stringify(**Your data**))`
if you have trouble with this, use `globEager` may save your day
***/
let modules = import.meta.globEager('/lang/*.json');
locales.forEach(locale => {
messages[locale] = modules[`/lang/${locale}.json`];
});
}
else {
// for webpack (storybook)
locales.forEach(locale => {
messages[locale] = require(`~/lang/${locale}.json`);
});
}
export default ({ app, store }) => {
app.i18n = new VueI18n({
locale: store.getters['locale/locale'],
messages
});
}
再次感谢@Lucas Dawson的回答!