+
75
-

vue3的cdn版本html如何动态载入vue组件运行?

vue3的cdn版本html如何动态载入vue组件运行?

网友回复

+
14
-

好的,这是一个非常实际且有用的需求,尤其是在不使用构建工具(如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%

我知道答案,我要回答