在 Vue 3 网站中运行已编译的 Vue 2 应用程序

问题描述 投票:0回答:1

我想知道是否有人有在 Vue 3 网站内运行已编译的 Vue 2 应用程序的策略。

我有一系列用 Vue 2 编写的小部件,我试图在由 Vue3 提供支持的网站中运行,但它似乎会发生冲突并导致副作用。

我想知道是否有某种非冲突模式可以编译我的小部件以确保 Vue 2 和 Vue 3 能够很好地配合?

vue.js vuejs2 vuejs3 vue-component
1个回答
0
投票

您可以使用 vue-custom-element 将您的 Vue 应用程序转换为 WebComponent 并像这样构建

vue-cli-service build --target lib --name widget-name --inline-vue --formats umd src/main.js

在你的

vue.config.js

function enableShadowCss(config)
{
  const configs = [
    config.module.rule('vue').use('vue-loader'),
  ];
  // based on common rules returned by `vue inspect`
  const ruleSets = ['css', 'postcss', 'scss', 'sass', 'less', 'stylus'];
  const ruleNames = ['vue-modules', 'vue', 'normal-modules', 'normal'];

  ruleSets.forEach((ruleSet) =>
  {
    if (config.module.rules.store.has(ruleSet))
    {
      ruleNames.forEach((rName) =>
      {
        if (config.module.rule(ruleSet).oneOfs.store.has(rName))
        {
          if (config.module.rule(ruleSet).oneOf(rName).uses.store.has('vue-style-loader'))
          {
            configs.push(config.module.rule(ruleSet).oneOf(rName).use('vue-style-loader'));
          }
        }
      });
    }
  });
  if (!process.env.BUILD_MODE)
  {
    process.env.BUILD_MODE = config.store.get('mode');
  }
  configs.forEach((c) => c.tap((options) =>
  {
    options.shadowMode = true;
    return options;
  }));
}

module.exports = {
  chainWebpack: config =>
  {
    enableShadowCss(config);
    return config;
  },
};

并且在你的

src/main.js

import vueCustomElement from 'vue-custom-element';
Vue.config.ignoredElements = ['widget-name'];

Vue.customElement('widget-name', App, {
  shadow: true,
  beforeCreateVueInstance(root)
  {
    const rootNode = root.el.getRootNode();

    if (rootNode instanceof ShadowRoot)
    {
      root.shadowRoot = rootNode;
    }
    else
    {
      root.shadowRoot = document.head;
    }
    root.i18n = i18n; // in case you're using Vue-i18n
    root.vuetify = vuetify; // in case you're using Vuetify

    // Monkey patch querySelector to properly find root element - otherwise v-menu, v-tooltip and similar do not work (Vuetify)
    const { querySelector } = document;
    document.querySelector = function(selector)
    {
      if (selector === '[data-app]') return root.shadowRoot.querySelector(selector);
      return querySelector.call(this, selector);
    };

    return root;
  },
});

widget-name
是新 WebComponent 的 HTML 标签 - 必须是多字短横线大小写。

© www.soinside.com 2019 - 2024. All rights reserved.