在 Vue Router 中有条件地导入一个组件
Conditionally import a component in Vue Router
我想有条件地在 vue 路由器中导入一个组件。这是我目前拥有的:
children: [
{
path: ':option',
component: () => import('../components/Option1.vue'),
},
],
根据 :option
是什么,我想导入不同的组件(Option1.vue
、Option2.vue
等)。我知道我可以放几个 children
但我实际上需要在我的父组件中使用 option
变量(如果路由有选项,我会进行测试)。
这怎么可能?
提前致谢:)
您可以创建一个包含 dynamic component 的加载器组件,而不是进行条件路由。在加载器中,您将根据路由参数有条件地延迟加载选项组件。这不仅在路由时更容易,您也不必手动导入任何东西,并且只会导入使用的选项。
步骤 1. 路由到选项加载器组件
路由器
{
path: ':option',
component: () => import('../components/OptionLoader.vue'),
}
步骤 2. 在该选项加载器模板中,使用一个动态组件,该组件将由一个名为 optionComponent
:
的计算确定
OptionLoader.vue
<template>
<component :is="optionComponent" />
</template>
步骤 3. 创建一个延迟加载当前选项的计算
OptionLoader.vue
export default {
computed: {
optionComponent() {
return () => import(`@/components/Option${this.$route.params.option}.vue`);
}
}
}
这将加载名为“Option5.vue”的组件,例如,当 option
路由参数为 5
时。现在您有了一个延迟加载的选项加载器,而不必手动导入每个选项。
编辑: OP 现在表示他正在使用 Vue 3。
Vue 3
对于 Vue 3,将计算更改为使用 defineAsyncComponent
:
OptionsLoader.vue
import { defineAsyncComponent } from "vue";
computed: {
optionComponent() {
return defineAsyncComponent(() =>
import(`@/components/Option${this.$route.params.option}.vue`)
);
}
}
这是在 VueJS3 中有效的东西:
<template>
<component :is="userComponent"/>
</template>
<script>
import { defineAsyncComponent } from 'vue';
import { useRoute, useRouter } from 'vue-router';
export default {
computed: {
userComponent() {
const route = useRoute();
const router = useRouter();
const components = {
first: 'Option1',
second: 'Option2',
third: 'OtherOption',
fourth: 'DefaultOption',
};
if (components[route.params.option]) {
return defineAsyncComponent(() => import(`./options/${components[route.params.option]}.vue`));
}
router.push({ path: `/rubrique/${route.params.parent}`, replace: true });
return false;
},
},
};
</script>
来源:https://v3.vuejs.org/guide/migration/async-components.html
对于带有“return
”的行,可能会收到类似这样的错误消息:
Syntax Error: TypeError: Cannot read property 'range' of null
在这种情况下,这意味着您可能想要从 babel-eslint
迁移到 @babel/eslint-parser
(来源:https://babeljs.io/blog/2020/07/13/the-state-of-babel-eslint#the-present)
我想有条件地在 vue 路由器中导入一个组件。这是我目前拥有的:
children: [
{
path: ':option',
component: () => import('../components/Option1.vue'),
},
],
根据 :option
是什么,我想导入不同的组件(Option1.vue
、Option2.vue
等)。我知道我可以放几个 children
但我实际上需要在我的父组件中使用 option
变量(如果路由有选项,我会进行测试)。
这怎么可能? 提前致谢:)
您可以创建一个包含 dynamic component 的加载器组件,而不是进行条件路由。在加载器中,您将根据路由参数有条件地延迟加载选项组件。这不仅在路由时更容易,您也不必手动导入任何东西,并且只会导入使用的选项。
步骤 1. 路由到选项加载器组件
路由器
{
path: ':option',
component: () => import('../components/OptionLoader.vue'),
}
步骤 2. 在该选项加载器模板中,使用一个动态组件,该组件将由一个名为 optionComponent
:
OptionLoader.vue
<template>
<component :is="optionComponent" />
</template>
步骤 3. 创建一个延迟加载当前选项的计算
OptionLoader.vue
export default {
computed: {
optionComponent() {
return () => import(`@/components/Option${this.$route.params.option}.vue`);
}
}
}
这将加载名为“Option5.vue”的组件,例如,当 option
路由参数为 5
时。现在您有了一个延迟加载的选项加载器,而不必手动导入每个选项。
编辑: OP 现在表示他正在使用 Vue 3。
Vue 3
对于 Vue 3,将计算更改为使用 defineAsyncComponent
:
OptionsLoader.vue
import { defineAsyncComponent } from "vue";
computed: {
optionComponent() {
return defineAsyncComponent(() =>
import(`@/components/Option${this.$route.params.option}.vue`)
);
}
}
这是在 VueJS3 中有效的东西:
<template>
<component :is="userComponent"/>
</template>
<script>
import { defineAsyncComponent } from 'vue';
import { useRoute, useRouter } from 'vue-router';
export default {
computed: {
userComponent() {
const route = useRoute();
const router = useRouter();
const components = {
first: 'Option1',
second: 'Option2',
third: 'OtherOption',
fourth: 'DefaultOption',
};
if (components[route.params.option]) {
return defineAsyncComponent(() => import(`./options/${components[route.params.option]}.vue`));
}
router.push({ path: `/rubrique/${route.params.parent}`, replace: true });
return false;
},
},
};
</script>
来源:https://v3.vuejs.org/guide/migration/async-components.html
对于带有“return
”的行,可能会收到类似这样的错误消息:
Syntax Error: TypeError: Cannot read property 'range' of null
在这种情况下,这意味着您可能想要从 babel-eslint
迁移到 @babel/eslint-parser
(来源:https://babeljs.io/blog/2020/07/13/the-state-of-babel-eslint#the-present)