【问题标题】:Vue- Import vue components dynamicallyVue - 动态导入 Vue 组件
【发布时间】:2019-04-23 16:26:33
【问题描述】:

我有很多组件,我想按需导入。我有一个下拉列表,其中实际上包含组件列表,即要加载的内容。我试过这个例子

<component :is="componentLoader"></component>

在脚本中

componentLoader () {
  return () => import('@/components/testDynamic') 
}

testDynamic 是一个组件名称(现在我正在尝试使用静态组件)。

收到此错误

GET http://localhost:8080/0.js net::ERR_ABORTED 404
[Vue warn]: Failed to resolve async component: function () {
    return __webpack_require__.e/* import() */(0).then(__webpack_require__.bind(null, "./src/components/testDynamic.vue"));
  }
  Reason: Error: Loading chunk 0 failed.

如何解决这个问题?我做错什么了吗?还是有其他方法可以动态导入组件?

【问题讨论】:

  • 也许可以试试return () =&gt; require('@/components/testDynamic')
  • 或者,注册他们globally
  • require 不会抛出任何错误,但它不会渲染任何东西。
  • @Andrew1325 全局注册的意思是,它将加载全局级别的所有组件,所有组件一次加载,可以在任何地方使用。但是它们最初都立即加载吗?我希望它仅按需导入。
  • 你在编译你的模板吗?因为也许它想在错误的地方导入,我建议尝试加载所有 50 个组件,看看它到底有多大,看看你是否需要像你认为需要的那样的解决方案......如果你真的需要它,我认为您必须单独生成/编译每个模板,然后将导入指向您放置它们的任何位置...

标签: javascript vue.js


【解决方案1】:

您可以像这样在单个文件组件中本地注册异步动态组件:

export default {
  components: {
    'test-dynamic': () => import('@/components/testDynamic'),
    'other-dynamic': () => import('@/components/otherDynamic')
  },
  data () {
    return {
      current: 'test-dynamic'
    }
  }
}

在你的模板中:

<component :is="current"></component>

如果您注册了多个组件,那么您只需将 current 的值更改为所需的组件。

在组件很多的情况下,你可以导入一个对象,将组件名称映射到它们各自的文件路径,然后像这样注册它们:

import myComponents from '@/components'

export default {
  components: Object.keys(myComponents).reduce((obj, name) => {
    return Object.assign(obj, { [name]: () => import(myComponents[name]) })
  }, {})
  ...
}

myComponents 导出为:

// components/index.js
export default {
  foo: '@/path/to/Foo',
  bar: '@/path/to/Bar',
  ...
}

【讨论】:

  • 在这种情况下,我们在components 部分中提到的任何组件最初都会被加载,对吗?我有近 50 个组件,导入所有这些组件/文件很重,对吗?这就是我尝试按需导入组件的原因。
  • 不,它们仅在需要时加载。
  • 嘿,我正在尝试你在组件部分提到的 'test-dynamic': () =&gt; import('@/components/testDynamic'),,但我仍然遇到同样的错误,我在问题中已经提到过。
  • 你在使用 vue cli 和/或 babel 吗?听起来好像没有正确转换代码?
  • 不确定,我使用vue init webpack . 创建了项目并且我正在尝试构建,它显示构建完成且没有错误,但这些错误出现在浏览器控制台中。我可以在 package.json 中看到 babel、babel-loader 和其他一些带有 babel 的东西。
【解决方案2】:

我遇到了同样的问题,因为我使用的是 Vue 3,所以这里给出的解决方案都不适合我。经过一番研究,我发现在 Vue 3 中定义动态组件(异步组件)的过程有些不同。 我希望这段代码对某人有所帮助。

<template>
    <component :is="comp"></component>
</template>

<script>
//Vue 3 is having a special function to define these async functions
import {defineAsyncComponent} from "vue";

export default {
 name: "DynamicComponent",
 //I am passing the name of the Component as a prop
 props: {
     componentName:{
         type: String,
         required: true
     }
 },
 computed: {
  comp () {
      return defineAsyncComponent(() => import(`@/components/${this.componentName}.vue`))
  }
}
}
</script>

【讨论】:

  • 如何动态获取子组件$emit的数据?
  • 组件不存在如何捕获错误?
【解决方案3】:

我经常使用下面的方法(Vue 2),效果很好。

以下简单示例允许动态指定要加载的组件: - 因为对 launchEditForm 的调用只需要一个字符串作为参数。 如果您可以将文件名表述为字符串,则可以加载它。

将 launchEditForm 保留为“计算”属性很重要,即不要在“方法”中定义它。

如果您调用的文件不存在,那么您将收到如下运行时错误: 找不到模块'./components/cliente/forms/DoesNotExist.vue'

<template>
  <div>
    <button
      type="button"
@click="launchEditForm('components/clients/forms/EditContactsForm.vue')"
    >
      Edit Contacts
    </button>
    <component :is="currentEditForm" />
  </div>
</template>
<script>
export default {
  name: 'Screen42',
  data() {
    return {
      componentToDisplay: null
    };
  },
  computed: {
    currentEditForm: function() {
      if (this.componentToDisplay) {
        return () => import(`@/${this.componentToDisplay}`);
      }
      return null;
    }
  },
  methods: {
    launchEditForm(fileName) {
      this.componentToDisplay = fileName;
    }
  }
};
</script>

请注意,在上面的示例中,文件位于 .../src/components/clients/forms/EditContactsForm.vue

这种类型的动态导入通常会在模态中完成,它只是将 标签按原样移动到模态内部的一种情况。显然,我们可以使用带有布尔变量的 v-if 来根据需要打开和关闭模态。但是上面的代码应该说明了核心点——即可以动态生成组件名称和动态加载组件。

【讨论】:

    【解决方案4】:

    对我有用的是等待 componentLoader 函数,因为 import 函数返回一个承诺!

    async componentLoader () {
      return await import('@/components/testDynamic') 
    }
    

    【讨论】:

      猜你喜欢
      • 2020-06-18
      • 2019-02-03
      • 2020-01-24
      • 2020-02-25
      • 2021-10-04
      • 2018-01-16
      • 1970-01-01
      • 2021-03-19
      • 2021-09-12
      相关资源
      最近更新 更多