网友回复
好的,这是一个非常实际且有用的需求,尤其是在不使用构建工具(如Vite、Webpack)的纯CDN环境中。
我们将通过Vue 3的 defineAsyncComponent 函数和一个自定义的加载器来实现这个功能。这种方法可以将您的应用模块化,保持主HTML文件的整洁,并按需加载组件。
核心思路
创建组件文件: 每个Vue组件将被写在一个独立的 .js 文件中。这个文件只包含组件的选项对象({ template: '...', data() {...} })。
全局注册: 为了让主应用能找到加载后的组件,每个组件文件在定义完自己后,会把自己注册到一个全局对象上(例如 window.VUE_COMPONENTS)。
自定义加载器: 我们会编写一个通用的JavaScript函数,该函数负责通过动态创建<script>标签来加载组件的URL。它会返回一个Promise,在脚本加载成功并找到注册的组件后,Promise会resolve。
defineAsyncComponent: 在主Vue应用中,我们使用 defineAsyncComponent 来包裹我们的自定义加载器。当Vue需要渲染这个组件时,它会自动调用我们的加载器,等待组件加载完成,然后渲染它。
项目文件结构
为了演示,你需要创建一个简单的项目结构,并使用一个本地服务器来运行它(因为浏览器安全策略限制直接从file://协议加载文件)。
/my-vue-app/ |-- index.html (主HTML文件) |-- /components/ | |-- Header.js (页头组件) | |-- UserProfile.js (用户资料组件) | |-- LoadingSpinner.js (加载中组件)
第1步:创建各个组件文件
/components/Header.js
这是一个简单的页头组件。
// /components/Header.js // 确保全局组件对象存在 window.VUE_COMPONENTS = window.VUE_COMPONENTS || {}; // 定义组件并注册到全局对象 window.VUE_COMPONENTS['AppHeader'] = { template: ` <header class="bg-white shadow-md"> <nav class="max-w-4xl mx-auto px-4 py-3 flex justify-between items-center"> <h1 class="text-xl font-bold text-indigo-600">动态组件加载系统</h1> <p class="text-sm text-gray-500">Vue 3 CDN 版</p> </nav> </header> ` };
/components/UserProfile.js
这是一个稍微复杂一点的组件,它接收props。
// /components/UserProfile.js window.VUE_COMPONENTS = window.VUE_COMPONENTS || {}; window.VUE_COMPONENTS['UserProfile'] = { props: ['userId'], template: ` <div class="bg-white p-6 rounded-lg shadow-lg border-l-4 border-emerald-500"> <div v-if="loading" class="text-gray-500">正在加载用户 {{ userId }} 的信息...</div> <div v-else> <div class="flex items-center space-x-4"> <img :src="user.avatar" class="h-16 w-16 rounded-full"> <div> <h2 class="text-2xl font-bold text-gray-800">{{ user.name }}</h2> <p class="text-gray-600">{{ user.email }}</p> </div> </div> </div> </div> `, data() { return { loading: true, user: null } }, created() { // 模拟API请求 setTimeout(() => { this.user = { name: '爱丽丝', email: 'alice@example.com', avatar: `https://i.pravatar.cc/150?u=${this.userId}` }; this.loading = false; }, 1000); } };
点击查看剩余70%