闽公网安备 35020302035485号
可能很多同学看到标题就会疑惑,什么场景才会出现将一个React组件放到Vue项目里使用。这难道不是技术选型没做好吗?其实在公司实际开发过程中,你会需要维护许多老项目,而这些老项目是Vue开发的,但是在公司新项目都是基于React,并且最重要的是基建部分是基于React的。
你就面临一个问题:例如公司基建有一个非常不错的基于React的Form表单生成组件,使用非常方便且熟悉,而在Vue老项目里依旧还是只能非常繁琐的编写Form表单,并且如果引入Vue能用的类似库会导致一定的学习成本、维护成本,这样子自然而然你就会想到React in Vue。
这个问题看似复杂,其实也很简单。因为其实我们完全不用考虑React 与 Vue的大部分差异性,例如生命周期限制等等。我们只需要将一个组件高度封装,只需要提供传递参数入口、获取实例的ref绑定即可,然后将一切渲染该React组件的事情都丢给reactDom.render()处理即可,这样子就能避免Vue无法处理React的特性。
// tsconfig.json
{
"compilerOptions": {
// ...
"types": [
"vite/client", // 当你使用vite
// ...
]
}
}
方案2export = React
export as namespace React
declare namespace React {
function createElement(...props: any[]): any
... // 你需要用到的React函数,这里只会用到createElement
}
注意你最好直接新建一个文件夹存放修改过的@types/react库。并将Package.json里的引用路径指向该文件,避免每次npm i 都需要重新修改dts文件。// 堆代码 duidaima.com
// ReactInVue胶水层组件
<template>
<div ref="container"></div>
</template>
<script lang="ts">
import { defineComponent, onMounted, PropType, reactive, ref, watch } from 'vue'
import reactDom from 'react-dom'
import react from 'react'
import { ReactComponent } from 'xxx'
export default defineComponent({
props: {
dependence: Object as () => Record<string, any>,
},
setup(props) {
const container = ref()
onMounted(() => {
reactDom.render(
react.createElement(ReactComponent, {
dependence: props?.dependence || {},
}),
container.value as Element
)
})
return {
container,
}
},
})
</script>
基于React 18 的基本实现Demo如下// ReactInVue胶水层组件
<template>
<div ref="container"></div>
</template>
<script lang="ts">
import { defineComponent, onMounted, PropType, reactive, ref, watch } from 'vue'
import reactDom from 'react-dom'
import react from 'react'
import { ReactComponent } from 'xxx'
export default defineComponent({
props: {
dependence: Object as () => Record<string, any>,
},
setup(props) {
const container = ref()
onMounted(() => {
const root = reactDom.createRoot(container.value)
root.render(React.createElement(ReactComponent, {
dependence: props?.dependence || {},
});
})
return {
container,
}
},
})
</script>
总结