Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

在react里渲染vue组件 #20

Open
yinxin630 opened this issue Jul 26, 2019 · 2 comments
Open

在react里渲染vue组件 #20

yinxin630 opened this issue Jul 26, 2019 · 2 comments

Comments

@yinxin630
Copy link
Owner

yinxin630 commented Jul 26, 2019

前言

是不是看标题就感觉很蛋疼?

最近项目在基于 react 重构, 但是依赖的一个公共业务组件是 vue 的, 并且暂时没有使用 react 重构的计划, 但是总不能一直等下去, 遂尝试在 react 里渲染 vue 组件

vuera

需要借助 vuera(https://github.com/akxcv/vuera) 来做这个事情

同时, webpack里需要同时配置 react 和 vue 的 loader

首先, 写一个典型的 vue 组件

// Module.vue
<template>
    <div>
        <span>click times: {{count}}</span>
        <br />
        <button @click="handleClick">+1s</button>
    </div>
</template>
<script>
export default {
    name: "Module",
    data() {
        return {
            count: 0
        }
    },
    methods: {
        handleClick() {
            this.count++;
        }
    }
}
</script>

然后, 在 react 里面渲染 vue 组件

// index.tsx
import React from 'react';
import { render } from 'react-dom';
import { VueWrapper } from 'vuera';
import Module from './Module.vue';
render(
    <div>
        <h2>下面是vue组件</h2>
        <VueWrapper component={Module} />
    </div>,
    document.getElementById('app'),
);

渲染效果:
image

向 vue 组件传参

react 里就像正常 react 组件一样传参即可

// index.tsx
<VueWrapper component={Module} msg="message pass by props" />

vue 里也是和正常 vue 组件一样, 定义 props

// Module.vue
<template>
    <div>
        <h3>{{msg}}</h3>
        ...
    </div>
</template>
<script>
export default {
    ...
    props: {
        msg: {
            type: String,
        }
    },
    ...
}
</script>

接收 vue 组件抛出的事件

在 vue 里面可以调用 this.$emit('xxx') 抛出事件

但是, react 组件里, 不能直接用 @xxx 或者 v-on:xxx 绑定事件, 但是可以通过 props 传递 function, 在 vue 组件里调用 props function

vue 组件对外抛出事件

// Module.vue
<script>
export default {
    ...
    props: {
        ...
        onCountChange: {
            type: Function
        }
    },
    methods: {
        handleClick() {
            this.count++;
            this.onCountChange(this.count);
        }
    }
}
</script>

如果 vue 组件不受自己控制, 不能修改源码的话, 也可以自己封装一层, 将 props function 转为 @xxx

使用 this.$emit() 的 vue 组件

// Module.vue
<script>
export default {
    ...
    methods: {
        handleClick() {
            this.count++;
            this.$emit('count-change', this.count);
        }
    }
}
</script>

创建中间适配层组件 MoudleWrapper

// ModuleWrapper.vue
<template>
    <div>
        <Module :msg="msg" @count-change="onCountChange"></Module>
    </div>
</template>
<script>
import Module from './Module.vue';
export default {
    name: "ModuleWrapper",
    components: { Module },
    props: {
        msg: {
            type: String,
        },
        onCountChange: {
            type: Function
        }
    },
}
</script>

修改入口文件, 改为渲染 MoudleWrapper 组件

// index.tsx
import React from 'react';
import { render } from 'react-dom';
import { VueWrapper } from 'vuera';
import MoudleWrapper from './MoudleWrapper.vue';
render(
    <div>
        <h2>下面是vue组件</h2>
        <VueWrapper component={MoudleWrapper} msg="message pass by props" onCountChange={console.log} />
    </div>,
    document.getElementById('app'),
);

打包

使用 vue 组件, 会把完整的 vue.js 打包进去

如果该 vue 组件并不是初始状态就需要展示的话, 可以做按需加载打成一个单独的 chunk, 使其不影响页面初始渲染时间

下面是一个按需加载的例子, 新增 App 组件来做动态展示和按需加载的逻辑

// App.tsx
import React, { useState, useEffect } from 'react';
import { VueWrapper } from 'vuera';
let MoudleWrapper: any = null;
export default function App() {
    const [showVueModule, toggleVueModule] = useState(false);
    function showHideVueModule() {
        if (MoudleWrapper) {
            toggleVueModule(!showVueModule);
        } else {
            import(/* webpackChunkName: "vue-module" */ './MoudleWrapper.vue').then(module => {
                MoudleWrapper = module.default;
                toggleVueModule(!showVueModule);
            });
        }
    }
    return (
        <div>
            <h2>下面是vue组件</h2>
            {
                showVueModule && MoudleWrapper
                    ? <div><VueWrapper component={MoudleWrapper} msg="message pass by props" onCountChange={console.log} /></div>
                    : null
            }
            <button onClick={showHideVueModule}>展示/隐藏vue组件</button>
        </div>
    );
}

运行效果如下:
image

@yinxin630 yinxin630 changed the title react里渲染vue组件 在react里渲染vue组件 Jul 30, 2019
@zhanghao1992
Copy link

我这边 现在是不显示 也不报错 您遇到过这情况么

@yinxin630
Copy link
Owner Author

我这边 现在是不显示 也不报错 您遇到过这情况么

只能一步步调试看看了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants