概述
import.meta
元属性将特定上下文的元数据暴露给 JavaScript 模块。它包含了这个模块的信息,例如这个模块的 URL。在vue3
项目中,用的比较多的是通过import.meta.env
来获取环境变量。而本文将要介绍的import.meta.glob
和import.meta.env
都是vite
提供的功能。
import.meta.glob
允许动态地加载多个模块而不需要显式地列出每个模块地路径。如果需要根据目录结构自动导入文件时,import.meta.glob
会非常有帮助。
为什么要用import.meta.glob
这里以实际工作中的一个功能需求为例。
需求:通过后端返回的type
去加载不同的表单form
,
文件目录结构如下
- 不用
import.meta.glob
<script setup>
import { ref, watch, computed } from "vue";
import { storeToRefs } from "pinia";
import { SYMBOL_TYPES } from "../../../const/const.map";
import Point from "./forms/Point.vue";
import Polygon from "./forms/Polygon.vue";
import Line from "./forms/Line.vue";
import Model from "./forms/Model.vue";
import Billboard from "./forms/Billboard.vue";
import Billboard_HLJB from "./forms/Billboard_HLJB.vue";
import Label from "./forms/Label.vue";
import LabelExt from "./forms/LabelExt.vue";
import { useMapMarkStore } from "../../../store/useMapMarkStore";
const mapMarkerStore = useMapMarkStore();
const { currentSymbol } = storeToRefs(mapMarkerStore);
const symbolInfo = ref({ ...currentSymbol.value });
watch(currentSymbol, (newValue) => {
symbolInfo.value = newValue;
});
const currentComponent = computed(() => {
const { type } = symbolInfo.value;
switch (type) {
case SYMBOL_TYPES.Polyline:
return Line;
case SYMBOL_TYPES.Point:
return Point;
case SYMBOL_TYPES.Polygon:
return Polygon;
case SYMBOL_TYPES.Model:
return Model;
case SYMBOL_TYPES.Label:
return Label;
case SYMBOL_TYPES.Billboard:
return Billboard;
case SYMBOL_TYPES.Billboard_HLJB:
return Billboard_HLJB;
default:
return null;
}
});
</script>
<template>
<div class="styleManageContent">
<component :is="currentComponent" />
</div>
</template>
上面的代码主要是通过watch
和computed
去监听type
,再通过switch
去匹配type
返回不同的form
组件。
- 使用
import.meta.glob
<script setup>
import { ref, watch, onMounted } from "vue";
import { storeToRefs } from "pinia";
import { SYMBOL_TYPES } from "../../../const/const.map";
import LabelExt from "./forms/LabelExt.vue";
import { useMapMarkStore } from "../../../store/useMapMarkStore";
const mapMarkerStore = useMapMarkStore();
const { currentSymbol } = storeToRefs(mapMarkerStore);
const symbolInfo = ref({ ...currentSymbol.value });
watch(currentSymbol, (newValue) => {
symbolInfo.value = newValue;
getCurrentComponent();
});
const currentComponent = ref({});
const getCurrentComponent = async () => {
const { type } = symbolInfo.value;
const modules = import.meta.glob(`./forms/*.vue`);
for (let path in modules) {
const componentName = path.split("/").pop().split(".").shift();
if (componentName == type) {
modules[path]().then((module) => {
currentComponent.value = module.default;
});
break;
}
}
};
onMounted(() => {
getCurrentComponent();
});
</script>
<template>
<div class="styleManageContent">
<component :is="currentComponent" />
<LabelExt v-if="symbolInfo.type != SYMBOL_TYPES.Label" />
</div>
</template>
使用import.meta.glob
,代码就简化了很多,不用导入所有的表单组件,也不用额外去定义常量SYMBOL_TYPES
。而且由于import.meta.glob
是动态导入,懒加载的方式会提高性能。
- 这里需要注意的一点就是
type
值需要和组件名对应上,或者有一个对应关系。
import.meta.glob
介绍
基本用法
import.meta.glob
接收一个字符串参数,且该参数不能是一个变量,因为import.meta.glob
的参数在构建时会被静态分析,用于生成构建时的文件列表,使用变量会导致这些路径在构建时无法明确具体的路径,导致Vite
无法解析和生成响应的模块导入代码。
关键点
-
路径匹配:支持路径通配符
-
返回值:返回值是一个对象,键是匹配的文件路径,值是动态导入函数
-
动态导入:返回的值可以动态导入,是一个异步操作
用途
-
动态加载路由组件、插件、视图等
-
实现懒加载以优化应用性能