vue react混合使用的几种方案:

React jsx 仅仅只是 React.createElement(component, props, ...children) 函数的语法糖。所有的jsx最终都会被转换成React.createElement的函数调用。

Vue jsx也仅仅是createElement函数(vue2) / h函数(vue3) 的语法糖。

Vue jsx转换(要用@vue/babel-preset-jsx解析为h函数) 和 React jsx转换(要用@babel/preset-react解析为React.createElement)有所区别。 而且 render函数生成的Vnode结构也有所不同。 编译时的处理也有所区别。

1.使用第三方库 vuera(vue2与react)  veaury(vue3 与 react)

vuera: https://github.com/akxcv/vuera

veaury: https://github.com/gloriasoft/veaury

这里以vuera为例:

(1).Vue中使用react:

<template>
  <div>
    <my-react-component :message="message" />
  </div>
</template>
<script>
  import { ReactInVue } from 'vuera'
  import MyReactComponent from './MyReactComponent'
  export default {
    data () {
      message: 'Hello from React!',
    },
    components: { 'my-react-component': ReactInVue(MyReactComponent) } //局部注册为vue component
  }
</script>

ReactInVue底层会使用到 封装的ReactWrapper 核心处理代码即

ReactDOM.render(React.createElement(Component, _extends({}, this.$props.passedProps, this.$attrs, this.$listeners, children, { ref: function ref(_ref) {  return _this2.reactComponentRef = _ref; }})), this.$refs.react);

(2)React中使用Vue:

import React from 'react'
import { VueInReact } from 'vuera'
import MyVueComponent from './MyVueComponent.vue'
export default () => {
  const Component = VueInReact(MyVueComponent)
  return (
    <div>
      <Component message='Hello from Vue!' />
    </div>
  )
}

VueInReact底层会使用到封装的VueContainer,核心处理代码即

reactThisBinding.vueInstance = new Vue(_extends({
        el: targetElement,
        data: props
      }, config.vueInstanceOptions, {
        render: function render(createElement) {
          return createElement(VUE_COMPONENT_NAME, {
            props: this.$data,
            on: on
          }, [wrapReactChildren(createElement, this.children)]);
        },
        components: (_components = {}, defineProperty(_components, VUE_COMPONENT_NAME, component), defineProperty(_components, 'vuera-internal-react-wrapper', ReactWrapper), _components)
      }));

vuera的babel插件 "plugins": ["vuera/babel"]

本质上是编译为__vueraReactResolver函数处理: return /*#__PURE__*/__vueraReactResolver(Calendar, { fullscreen: fullscreen || false });
exports.__vueraReactResolver = babelReactResolver$$1;
function babelReactResolver$$1(component, props, children) {
  return isReactComponent(component) ? React.createElement(component, props, children) : React.createElement(VueContainer, Object.assign({ component: component }, props), children);
}

2.自行通过new Vue/ReactDOM 进行渲染

2-1.vue中使用react: 主要问题是vue无法识别react的 jsx语法。

配置babel 解决jsx语法,webpack.config.js中:

module.exports = {
    module: {
      rules: [
        {
          test: /.(js|jsx)$/,
          exclude: /node_modules/,
          use: {
            loader: 'babel-loader',
            options:{
              "presets": ["@babel/preset-react", "@babel/preset-env"],
              "plugins": ["@babel/plugin-transform-runtime"]
            }
          }
        }
      ]
   }
}

渲染React组件:

import React from 'react';
import * as ReactDOM from 'react-dom/client';
import Test from "./test.jsx"
<div id="reactApp"></div> 
  mounted () {
      const container = document.getElementById('reactApp');
      const root = ReactDOM.createRoot(container);
      root.render(<Test />); //这个写法是 react-dom的18版本的写法 
      // 18版本之前的话,这样处理: ReactDOM.render( React.createElement(Test, null), document.getElementById('reactApp') );
  }

2-2.react中使用vue: 主要问题是react无法解析.vue文件(组件)

配置vue-loader解决.vue文件解析问题。

// 在 webpack.config.js 内
const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
  mode: 'development',
  module: { rules: [ { test: /.vue$/, loader: 'vue-loader' } ] },
  plugins: [ new VueLoaderPlugin() ]
}

渲染Vue组件:

import Vue from 'vue' 
import Test from "./test.vue"; //需要vue-loader解析.vue文件
export default class App extends Component {
  componentDidMount() {
    new Vue({ render: h => h(Test) }).$mount('#vueApp');
  }
  render() { return <div id="vueApp" /> }
}
//直接渲染vue的组件选项对象的话 无需配置vue-loader解析,直接引入全量Vue库处理即可,如下:
const Test = {  
    template: ` <div> ....... </div> `, 
    data () { return { } } 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李庆政370

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值