react 包裹vue组件

157 阅读1分钟
import React from 'react';
import Vue from 'vue';
import _ from 'lodash';

interface IVueWrapperProps {
  /** vue组件 */
  component: any;
  /** 注入进vue的数据 */
  data: {
    [key: string]: any;
  };
  /** 注入的key值  */
  injectData: string[];
  /** 注入进vue的全局方法 */
  injectMethods?: Array<Function>;
}
interface IVueWrapperState {
  /** vue实例 */
  instance: any;
}
class VueWrapper extends React.Component<IVueWrapperProps, IVueWrapperState> {
  myRef: any = React.createRef();

  constructor(props: IVueWrapperProps) {
    super(props);
    this.state = {
      instance: null,
    };
  }

  componentDidMount() {
    const instance = this.bindVueInElement();
    this.setState({
      instance,
    });
  }

  shouldComponentUpdate(nextProps: any) {
    const { instance } = this.state;
    const { data, injectData } = this.props;
    if (!_.isEqual(data, nextProps.data)) {
      if (instance) {
        instance.selfWare = nextProps.data.selfWare;
        instance.isAdmin = nextProps.data.isAdmin;
        injectData.forEach((item) => {
          instance[item] = nextProps.data[item];
        });
      }
      return true;
    }
    return false;
  }

  componentWillUnmount() {
    const { instance } = this.state;
    if (instance) {
      instance.$destroy();
      this.setState({
        instance: null,
      });
    }
  }

  bindVueInElement = () => {
    const { component, data, injectMethods } = this.props;
    const instance = new Vue({
      render(h) {
        return h(component);
      },
      provide() {
        return {
          isAdmin: true,
          app: this,
        };
      },
      data() {
        return {
          ...data,
        };
      },
      methods: {
        ...injectMethods,
      },
    });
    if (this.myRef && this.myRef.current) {
      instance.$mount(this.myRef.current);
    }
    return instance;
  };

  render() {
    return (
      <div>
        <div ref={this.myRef} />
      </div>
    );
  }
}

export default VueWrapper;