我们正在尝试更新一个库,新版本需要 Vue 3 而不是 Vue 2,即tinymce-vue。不幸的是,这是一个使用 bootstrap-vue 的公司项目,尚未与 Vue 3 完全兼容(bootstrap-vue3 尚未做好生产准备,我们使用了一些尚未迁移的组件)。
将完整的应用程序迁移到 Vue 3 是主要尝试。但是,它不允许在 Vue 3 中使用 Bootstrap 组件,或者如果使用兼容模式,应用程序的一部分可以工作,但需要该组件的部分不会出现/工作,或者组件的其他部分需要 Vue 3个坏了。有没有什么方法可以提供特定于库的兼容性,或者在这种情况下,当需要两个库在同一组件中需要两个不同版本的 Vue 时,建议的方法是什么?
我不确定这个问题是否应该以不同的方式提出,这是我在 StackOverflow 中的第一个问题,所以如果我需要重新表述或提供更多详细信息,请告诉我。
P粉0463871332023-12-29 15:53:24
问题在于,Vue 2 和 3 应用程序很难甚至不可能在同一个项目中共存,因为它们依赖于同名但不同版本的 vue
包。即使可以使用不同名称的 vue
包别名或使用模块化 Vue(import Vue from 'vue'
)作为一个版本和 Vue CDN (window. Vue
)对于第一方代码中的另一个版本,另一个需要解决的问题是Vue库需要使用特定的Vue版本。
这需要使用其首选的 Vue 版本和库来构建和捆绑子应用程序,这与微前端应用程序的概念非常接近。
假设有一个 Vue 3 子应用程序使用 Vue 3 特定库 (tinymce-vue),并专门编写用于公开所有公共 API 以与外界通信:
let MyV3Comp = { template: `<div>{{ myV3Prop }} {{ myV3Data }}</div`, props: ['myV3Prop'], emits: ['myV3Event'], setup(props, ctx) { const myV3Data = ref(1); const myV3Method = () => {}; ctx.emit('myV3Event', Math.random()); // Component public api needs to be exposed to be available on mount() instance ctx.expose({ myV3Data, myV3Method }); return { myV3Data, myV3Method } }, }; // Sub-app entry point let createMyV3App = initialProps => createApp(MyV3Comp, initialProps); export default createMyV3App;
Vue 2 包装组件充当 Vue 3 子应用程序和 Vue 2 应用程序其余部分之间的桥梁:
import createMyV3App from '.../my-v3-app-bundled'; let MyV2WrapperComp = { template: `<div ref="v3AppWrapper"></div>`, props: ['myV2Prop'], emits: ['myV2Event'], data() { return { myV2Data: null }; }, methods: { // Sync wrapper events onMyV3Event(v) { this.$emit('myV2Event', v); } }, watch: { // Sync wrapper props and data myV2Data(v) { this.v3AppCompInstance.myV3Data.value = v; }, myV2Prop(v) { // Hacky! Better use data and methods from public api to pass info downwards this.v3AppCompInstance._instance.props.myV3Prop = v; }, }, mounted() { // Vue 3 automatically translates onMyV3Event prop as myV3Event event listener // Initial prop values make app props reactive // and allow to be changed through _instance.props this.v3App = createMyV3App({ onMyV3Event: this.onMyV3Event, myV3Prop: null }); // also available as undocumented this.v3App._instance.proxy this.v3AppCompInstance = this.v3App.mount(this.$refs.v3AppWrapper); // Sync wrapper data // Hacky! Better use event from public api to pass info upwards this.v3AppCompInstance._instance.proxy.$watch('myV3Data', v => this.myV2Data = v); }, unmounted() { this.v3App.unmount(); }, };
如果包装器和子应用程序需要根据特定点进行额外同步,例如provide
/inject
、模板引用等,这个需要具体实现。在这一点上,它与 Vue 3->Vue 2 适配器或涉及其他框架(Angular、React)的适配器没有什么不同。