【问题标题】:Optionally import Component in Vue可选地在 Vue 中导入组件
【发布时间】:2021-04-18 10:36:30
【问题描述】:

我有几种菜单类型,想配置要在 .env.local 中使用的菜单类型,例如:VUE_APP_MENU_TYPE=2

在我的 javascript 文件中,我有以下内容:

let menu = false;
if (process.env.VUE_APP_MENU_TYPE === "2") {
  menu = require("./type2/Type2.vue");
}
if (menu === false) {//default menu if env is missing
  menu = require("./default/Default.vue");
}
export default menu;

这将导致错误Failed to mount component: template or render function not defined.

我可以做到以下几点:

import Default from "./default/Default.vue";
import Type2 from "./type2/Type2.vue";
let menu = Default;
if (process.env.VUE_APP_MENU_TYPE === "2") {
  menu = Type2;
}
export default menu;

这将起作用,但所有菜单都在代码中编译,包括永远不会使用的菜单,因为 VUE_APP_MENU_TYPE 在编译时是已知的,并且在您重新编译之前永远不会改变。

是否可以在编译时动态导入组件?

【问题讨论】:

    标签: javascript vue.js vuejs2 vue-component


    【解决方案1】:

    试试menu = require("./type2/Type2.vue").default;

    来自answer的解释

    在处理 ES6 导入 (export default MyComponent) 时,导出的模块格式为 {"default" : MyComponent}。 import 语句为您正确处理此分配,但是,您必须自己进行 require("./mycomponent").default 转换。如果您想避免这种情况,请使用 module.exports 而不是 export default

    问题的第二部分...

    是否可以在编译时动态导入组件?

    真的从未尝试过,但我有疑问。 Webpack 在构建时不执行代码。它只是扫描它的一些模式。

    1. 它会扫描require(),因此它知道应该在包中包含哪些模块
    2. DefinePlugin 将 process.env.VUE_APP_MENU_TYPE 之类的字符串替换为 env 文件中的值,因此它使代码看起来像 if ("3" === "2") {
    3. 其他插件能够检测到 if ("3" === "2") { 永远不是 true 并消除“死亡密码”

    真正的问题是先发生什么 - 如果require 扫描发生在消除死亡代码之前,您最终将获得捆绑中所有可能的菜单组件。但不幸的是我不知道 - 你必须尝试

    另一方面,使用dynamic async components(如其他答案中所述)是肯定的。是的,Webpack 将构建所有可能的菜单组件,但每个组件都有自己的 js 块(dist 文件夹中的 js 文件)。如果应用程序只加载其中一个,对我来说似乎没问题(请注意加载将是异步的 - 在运行时 - 所以这意味着多了一个服务器请求)

    【讨论】:

    • 我喜欢 require 的方式比别名 webpack 配置更好,所以我会继续这样做。谢谢你的回答。
    【解决方案2】:

    我认为动态加载组件是您拥有的最佳选择。 https://vuejs.org/v2/guide/components-dynamic-async.html

    【讨论】:

    • 感谢您的回复。我认为使用这些方法将使组件成为构建的一部分。假设我有 20 种不同类型的菜单,那么所有 20 种菜单都是构建的一部分,但我只需要 1 个,这是我在构建时已经知道的。我正在寻找一种方法,以便其他 19 个不会成为构建的一部分。
    • 我已经动态加载了组件,但我不知道如何动态构建它。我让它工作的方式需要所有组件成为构建的一部分,即使是我永远不会用于构建的组件
    • 动态异步组件不是捆绑包的一部分。是的,它们被编译成各自独立的 JS 块。所以文件将在dist 文件夹中,但如果应用程序从不加载他们,谁在乎呢?
    • @HMR 动态导入被打包到单独的 .chunk 文件中,因此客户端不会加载不需要的内容。
    • @MichalLevý 谢谢,所以异步是另一种选择。它会构建不必要的代码,但从不加载它。
    【解决方案3】:

    我可以通过 webpack 设置解决这个问题。

    在 vue.config.js 中

    const path = require("path");
    
    module.exports = {
      configureWebpack: {
        resolve: {
          alias: {
            MENU: path.resolve(
              __dirname,
              (() => {
                if (process.env.VUE_APP_MENU_TYPE === "2") {
                  return "src/components/header/CategoriesMenu/Type2/Type2.vue";
                }
                return "src/components/header/CategoriesMenu/Default/Default.vue";
              })()
            ),
          },
        },
      },
    };
    

    在 src/components/header/CategoriesMenu/index.js 中

    import menu from "MENU";
    export default menu;
    

    但老实说,我更喜欢require。

    【讨论】:

      猜你喜欢
      • 2021-05-01
      • 2022-01-09
      • 2021-03-25
      • 2018-01-16
      • 1970-01-01
      • 2017-06-19
      • 2017-01-27
      • 2019-04-23
      • 2017-05-18
      相关资源
      最近更新 更多