红茶的个人站点

  • 首页
  • 专栏
  • 开发工具
  • 其它
  • 隐私政策
Awalon
Talk is cheap,show me the code.
  1. 首页
  2. 其它
  3. 正文

前端学习笔记 8:动态加载组件

2025年6月9日 6点热度 0人点赞 0条评论

假设有一个提交申请的入口页:

image-20250609210425041

页面代码位于views/Home.vue:

<template>
  <div>
    <div
      style="
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        height: 100vh;
      "
    >
      <h1>首页</h1>
      <!-- // 用forms 数据渲染三个超链接 -->
      <div v-for="form in forms" :key="form.key" style="margin: 10px 0">
        <el-link @click="loadForm(form.key)" type="primary">{{ form.name }}</el-link>
      </div>
    </div>
  </div>
</template>
​
<script>
import { ref } from "vue";
import { useRoute, useRouter } from "vue-router";
export default {
  name: "Home",
  components: {},
  data() {
    return {};
  },
  methods: {},
  setup() {
    const router = useRouter();
    const forms = ref([
      { name: "采购申请", key: "BuyForm" },
      { name: "请假神", key: "HolidayForm" },
      { name: "出差申请", key: "TravelForm" },
    ]);
    const loadForm = (formKey) => {
      console.log(formKey);
      router.push({ path: "/dynamicForm/" + formKey });
      return;
    };
    return { forms, loadForm };
  },
};
</script>

这里的申请链接点击后,会路由到/dynamicForm这个带路径参数的地址。

路由定义:

import DynamicForm from '@/views/DynamicForm.vue'
// 定义路由规则
const routes = [
    { path: '/', component: HomeVue },
    { path: '/dynamicForm/:name', component: DynamicForm }
]

在DynamicForm.vue中,获取路径参数,并且根据路径参数动态加载子组件:

<template>
  <div class="button-container">
    <el-button @click="goBack" type="primary" class="back-button"
      >返回申请列表页</el-button
    >
  </div>
  <div class="form-container">
    <!-- 使用component is动态绑定异步组件 -->
    <component :is="AsyncComp" v-if="AsyncComp && !isLoading" />
    <!-- 添加加载状态提示 -->
    <div v-else class="loading-text">表单加载中...</div>
  </div>
</template>
​
<style scoped>
.button-container {
  display: flex;
  justify-content: center;
  margin-bottom: 20px;
}
</style>
​
<script>
import { useRoute, useRouter } from "vue-router";
import Formloading from "../components/Loading.vue";
import FormloadError from "../components/Error.vue";
import { ref, defineAsyncComponent, onMounted } from "vue";
export default {
  name: "DynamicForm",
  setup() {
    const AsyncComp = ref(null);
    // 从路由获取路径参数
    const route = useRoute();
    const router = useRouter();
    const name = route.params.name;
    const componentPath = `../components/form/${name}.vue`;
    const isLoading = ref(true);
    // 定义异步组件
    AsyncComp.value = defineAsyncComponent({
      loader: () => import(componentPath),
      loadingComponent: Formloading,
      errorComponent: FormloadError,
      delay: 200,
      timeout: 3000,
    });
    const goBack = () => {
      router.push({ path: "/" });
    };
    onMounted(() => {
      isLoading.value = false;
    });
    return { AsyncComp, goBack, isLoading };
  },
};
</script>

这里的Formloading和FormloadError是加载中和加载失败时展示的备选组件。

不同的申请单位于components/form/xxx.vue。

需要注意的是,在使用 defineAsyncComponent 方法异步加载子组件时,import 方法接收的需要动态加载的组件路径只能是相对路径,比如./xxx或../xxx这样。如果路径是@/components/...这样,会报错,错误信息显示找不到对应的页面。

在上面这个示例中,这样动态加载子组件显得不是那么必要。完全可以使用import xxx from xxx加载所有的子组件,然后按照需要使用。但如果子组件过多,这样会有不必要的性能消耗,此外,如果申请单有迭代需求,比如有多个版本(v1,v2,v3等等),可以通过服务端配置来决定当前使用的是哪个申请单组件。

除了这种方式外,更灵活的是将 vue 源码放在服务端(比如数据库),页面加载时从服务端获取并加载,可以看作是“真动态加载”,但那样需要使用 vue 的编译器,将 vue 源码编译为 js 和 html,然后加载。步骤繁琐且容易遇到各种技术问题,且可能会带来安全隐患。

本文的完整示例代码可以从这里获取。

The End.

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: vue 前端
最后更新:2025年6月9日

魔芋红茶

加一点PHP,加一点Go,加一点Python......

点赞
< 上一篇

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

*

code

COPYRIGHT © 2021 icexmoon.cn. ALL RIGHTS RESERVED.
本网站由提供CDN加速/云存储服务

Theme Kratos Made By Seaton Jiang

宁ICP备2021001508号

宁公网安备64040202000141号