可能很多同学看到标题就会疑惑,什么场景才会出现将一个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 // ... ] } }方案2
export = 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>总结