美文网首页
开发跨框架使用组建(react组件为例)

开发跨框架使用组建(react组件为例)

作者: 是嘤嘤嘤呀 | 来源:发表于2020-04-18 16:16 被阅读0次

    背景

    在前端开发中,组件封装已经成为工作当中不可或缺的一部分,但是很多时候,我们封装好的组件只能满足在某一特定框架下使用,一旦有别的框架想要接入使用我们封装好的组件,我们通常需要重新写一套可以适配的组件提供出去。那么如何才能更大程度的利用我们已有的组件,也是一个值得大家讨论的问题。

    已有解决方式

    1、iframe
    iframe的优缺点很明显,其中最重要的就是跨域cookie同步问题,有需要的可以参考iframe页面cookie同步解决方案。

    2、web-components
    web-components是谷歌公司近几年推出的原生组件解决方案,其最大的问题在于浏览器兼容性问题。
    3、vuera等工具
    vuera等一定程度上可以满足我们的需求,但是其种类繁多,且各个框架有各自的工具,使用成本较高。

    通过挂载的方式解决

    例如我们想开发以下这样一个时钟组件,并要求其可以在react框架以外也可以使用:


    可以停止的时钟组件

    step1: 正常开发组件

    import {Button} from "antd";
    import moment from 'moment';
    import PropTypes from "prop-types";
    // 正常开发组件
    class MoreComp extends React.Component {
      constructor(props) {
        super(props);
        this.interId = null
        this.state = {
          time: null
        }
      }
      static propTypes = {
        lable: PropTypes.string
      };
      static defaultProps = {
        lable: "当前时间为"
      }
      componentDidMount() {
        this.interId = setInterval(() => {
          this.setState({
            time: moment().format('YYYY-MM-DD h:mm:ss')
          })
        }, 1000)
      }
      handleCancel() {
        this.interId && clearInterval(this.interId);
      }
      render() {
        const {lable} = this.props;
        const {time} = this.state;
        return (
          <div>
            {time && <span>{`${lable}: ${time}`}</span>}
            <Button onClick={() => this.handleCancel()} type="primary">停止</Button>
          </div>
        );
      }
    }
    export default MoreComp;
    

    step2: 测试没有问题以后,对组件进行改造

    import { Button } from "antd";
    import moment from "moment";
    import PropTypes from "prop-types";
    // 正常开发组件
    class MoreComp extends React.Component {
      constructor(props) {
        super(props);
        this.interId = null;
        this.state = {
          time: null,
        };
      }
      static propTypes = {
        lable: PropTypes.string,
      };
      static defaultProps = {
        lable: "当前时间为",
      };
      componentDidMount() {
        this.interId = setInterval(() => {
          this.setState({
            time: moment().format("YYYY-MM-DD h:mm:ss"),
          });
        }, 1000);
      }
      handleCancel() {
        this.interId && clearInterval(this.interId);
        this.props.handleCancel();
      }
      render() {
        const { lable } = this.props;
        const { time } = this.state;
        return (
          <div>
            {time && <span>{`${lable}: ${time}`}</span>}
            <Button onClick={() => this.handleCancel()} type="primary">
              停止
            </Button>
          </div>
        );
      }
    }
    window.moreComp = function (domId, props) {
      let dom = document.getElementById(domId);
      if (dom) {
        ReactDOM.render(<MoreComp {...props} />, dom);
      }
    }
    
    // export default MoreComp;
    

    step3: 打包组件
    step4: 在VUE项目中使用组件


    在VUE项目中使用react组件效果图
    // 使用方式
    <template>
      <div class="wrapper">
        <div class="tips">this is a demo for using React component in VUE </div>
        <div id="moreComp"></div>
      </div>
    </template>
    
    <script>
    import renderComp from "./renderComp.js"
    export default {
      data() {
        return {};
      },
      mounted() {
        console.log(this.handleCancel)
        renderComp("moreComp", "http://localhost:4000/more-comp/cdn/index.js", {lable: "this is a clock that could be stoped", handleCancel: this.handleCancel});
      },
      methods: {
        handleCancel(){
          console.log(this)
        }
      }
    };
    </script>
    
    <style scoped>
    .wrapper {
      margin: 0 auto;
    }
    .tips {
      height: 100px;
      line-height: 100px;
      font-weight: bold;
      font-size: 22px
    }
    #moreComp {
      height: 100px;
      width: 500px;
      text-align: "center";
      border: solid 1px #eee;
      line-height: 100px;
      padding-left: 10px;
    }
    </style>
    
    // renderComp.js
    function renderComp(id, src, props) {
        let script = document.createElement("script");
        script.type = "text/javascript";
        script.src = src;
        script.onload = script.onreadystatechange = function() {
          if (script.ready) {
            return false;
          }
          if (
            !script.readyState ||
            script.readyState == "loaded" ||
            script.readyState == "complete"
          ) {
            console.log(id, props);
            moreComp(id, props)
          }
        };
        document.body.appendChild(script);
    }
    
    export default renderComp;
    

    总结:

    用类似的方式可以实现该组件在HTML文件、React项目、Angular项目中使用组件。另外,为了不影响打包后的组件在React项目中的正常使用,还应该在设计的时候更加精细,且调用方法过于繁琐,可以考虑封装成独立的方法,用来简化使用流程。

    相关文章

      网友评论

          本文标题:开发跨框架使用组建(react组件为例)

          本文链接:https://www.haomeiwen.com/subject/pauvvhtx.html