Vue3 也能用上 Vue2 组件 From EMP
转自团队原文:https://juejin.cn/post/6898498514813190158说在前面上篇文章讨论完怎么在React 和 Vue 互相调用之后,我们发现了新的需求。升级 Vue3 之后,因为底层的 render 函数被重写,导致 Vue2 现有丰富并完善的组件不能直接在 Vue3 上使用。因此 EMP 针对这个问题,提出了 Vue3 调用 Vue2 的方案,并且付诸实践证实可行
转自团队原文:https://juejin.cn/post/6898498514813190158
说在前面
上篇文章讨论完怎么在 React 和 Vue 互相调用之后,我们发现了新的需求。
升级 Vue3 之后,因为底层的 render 函数被重写,导致 Vue2 现有丰富并完善的组件不能直接在 Vue3 上使用。因此 EMP 针对这个问题,提出了 Vue3 调用 Vue2 的方案,并且付诸实践证实可行。
所以我们实现了 emp-vuett,一个跨越 Vue 版本的 HOC。
先看 demo
demo 链接:
git clone emp ,然后 yarn global add lerna && yarn && rm -rf node_modules/vue && lerna bootstrap && cd projects && dev:vue23
将启动以下项目:
Vue3-project
Vue2-base
在 Vue3 下调用 Vue2 组件
Vue2 组件自身
使用
安装 emp-vuett
yarn add @efox/emp-vuett or npm i @efox/emp-vuett
Vue3 调用 Vue2 组件
- 使用
npx @efox/emp-cli init
新建一个 Vue3 项目 - 选择 Vue3
3. 在项目里引入 @efox/emp-vuett
4. 引入一个 Vue2 的组件 4. 新建一个空 dom
,且赋予一个 id 5. 把 Vue2 组件和空dom
id传入 @efox/emp-vuett
完整代码用例:
<template>
<div>
<h1>VUE 3 Project</h1>
<v3b-button />
<!-- 为了保持加载顺序需要挂载一个空的 dom ,将 id 传给 emp-vuett-->
<div id="content"></div>
<conent-in-vue3
:dataProps="num"
:methodProps="propsFunc"
@myEvent="emitFunc"
/>
<v3b-content />
</div>
</template>
<script>
import { defineAsyncComponent, render } from "vue";
// Vue2 组件
import Content from "@v2b/Content";
// Vue2 在 Vue3 运行的 HOC
import { Vue2InVue3 } from "@efox/emp-vuett";
// 让 Vue2 组件通过 emp-vuett 可以在 Vue3 上运行
// 传入 Vue2 组件和当前模板一个空div的id
const ContentInVue3 = Vue2InVue3(Content, "content");
export default {
components: {
"conent-in-vue3": ContentInVue3,
},
data() {
return {
num: 0,
};
},
methods: {
// 正常传递 props 到 Vue2 组件
propsFunc() {
console.log("Vue3 to Vue2 Method Props");
},
// 可以正常在 Vue2 组件上使用 emit
emitFunc() {
this.num++;
},
},
setup() {},
mounted() {},
name: "App",
};
</script>
on,props,attrs,slot 等等都可以正常使用
注意:由于 Vue3 把 $listeners 移除里,被 Vue3 调用的 Vue2 组件需要做以下调整
// Vue2 使用 Vue3 传过来的自定义事件需要把函数名 kebab-case 改为 camelCase 再加前缀 on
// 例如:调用 @myEvent 需要写成 onMyEvent
// 被 Vue3 调用
this.$emit("onMyEvent");
// 被 Vue2 调用
this.$emit("myEvent");
emp-vuett 原理
EMP 远程调用 Vue2 组件
上述被调用的 Vue2 组件都是通过 EMP 微前端远程调用的。
想要远程调用组件,只需要引用项目和被引用项目进行以下两步:
npm i -g @efox/emp-cli or yarn global add @efox/emp-cli
2.新建 emp-config.js,并配置(了解更多 EMP 使用,请看 EMP 系列教程)
/vue2-base/emp-config.js
const withVue2 = require('@efox/emp-vue2')
module.exports = withVue2(({config}) => {
const projectName = 'vue2Base'
const port = 8009
config.output.publicPath(`http://localhost:${port}/`)
config.devServer.port(port)
config.plugin('mf').tap(args => {
args[0] = {
...args[0],
...{
name: projectName,
library: {type: 'var', name: projectName},
filename: 'emp.js',
exposes: {
'./Content': './src/components/Content',
},
shared: ['vue/dist/vue.esm.js'],
},
}
return args
})
config.plugin('html').tap(args => {
args[0] = {
...args[0],
...{
title: 'EMP Vue2 Base',
},
}
return args
})
})
/vue3-project/emp-config.js
const withFrameWork = require('@efox/emp-vue3')
module.exports = withFrameWork(({config}) => {
const projectName = 'vue3Project'
config.output.publicPath('http://localhost:8006/')
config.devServer.port(8006)
config.plugin('mf').tap(args => {
args[0] = {
...args[0],
...{
name: projectName,
library: {type: 'var', name: projectName},
filename: 'emp.js',
remotes: {
'@v2b': 'vue2Base',
},
exposes: {},
/* shared: {
vue: {eager: true, singleton: true, requiredVersion: '^3.0.2'},
}, */
},
}
return args
})
config.plugin('html').tap(args => {
args[0] = {
...args[0],
...{
title: 'EMP Vue3 Project',
files: {
js: ['http://localhost:8009/emp.js'],
},
},
}
return args
})
})
总结
- 通过 EMP 的加持,远程调用 Vue2 组件,极大方便了组件的复用。
- 通过利用 Vue3 的生命周期和 Vue2 的 Runtime 实现了在 Vue3 上无缝使用 Vue2 组件,极大丰富了 Vue3 的生态。
作者
Benny Shi | Ken.Xu |
更多推荐
所有评论(0)