编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

支持Vue、React混用的veaury库大火?前端摆脱二选一?

wxchong 2025-01-03 19:23:53 开源技术 640 ℃ 0 评论

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!

1.什么是Veaury?

Veaury(发音为 /?vju?ri/,灵感来自“beauty”)是一个工具库。 它建立在 Vue 和 React 框架之上。 它的用例包括在一个应用程序中同时使用 Vue 和 React,从 React 迁移到 Vue 或从 Vue 迁移到 React,以及使用第三方 Vue 和 React 组件,例如 antd、element-ui、vuetify。

2.Veaury的特点

  • 支持 Vue3
  • 支持上下文 - 共享所有 vue 和 react 组件的上下文。
  • 支持跨框架使用 hooks - 你可以在 Vue 组件中使用 React 的 hooks,或者你可以在 React 组件中使用 Vue 的 'setup' 函数,并在这个函数中使用 Vue 的 hooks。
  • 纯模式 - 转换后的组件的子组件不再有额外的元素容器。

3.使用场景

  • ?? 在一个应用程序中同时使用 Vue 和 React
  • 从 React 迁移到 Vue 或从 Vue 迁移到 React
  • 使用第三方 Vue 和 React 组件,例如 antd、element-ui、vuetify等

4.是否需要提前预配置项目?

理论上,你不需要在 React 项目中做额外的配置来支持 Vue,也不需要在 Vue 项目中做额外的配置来支持 React。

如果你要转换的 React 或 Vue 组件来自 npm 包,或者已经构建(不是直接的 vue 文件,不包含 jsx),你可以直接使用 applyPureReactInVue 或 applyVueInReact。

如果你需要在项目中同时开发 Vue 和 React,而不是仅仅使用现有的 npm 组件(项目源代码中既有 .vue 文件,也有 react jsx 文件),那么你应该做一些配置。

如果是vite搭建的项目,相关配置如下。 首先安装@vitejs/plugin-react、@vitejs/plugin-vue 和@vitejs/plugin-vue-jsx。

4.1 主项目是Vue

import { defineConfig } from 'vite'
// >= veaury@2.1.1
import veauryVitePlugins from 'veaury/vite/index.js'

export default defineConfig({
  plugins: [
    // Turn off vue and vuejsx plugins
    // vue(),
    // vueJsx(),
    // When the type of veauryVitePlugins is set to vue, 
    // only jsx in files in the directory named 'react_app' will be parsed with react jsx,
    // and jsx in other files will be parsed with vue jsx
    veauryVitePlugins({
      type: 'vue',
      // Configuration of @vitejs/plugin-vue
      // vueOptions: {...},
      // Configuration of @vitejs/plugin-react
      // reactOptions: {...}, 
      // Configuration of @vitejs/plugin-vue-jsx
      // vueJsxOptions: {...}
    })
  ]
})

4.2 主项目是React

import { defineConfig } from 'vite'
// >= veaury@2.1.1
import veauryVitePlugins from 'veaury/vite/index.js'

export default defineConfig({
  plugins: [
    // Turn off react plugin
    // react(),
    // When the type of veauryVitePlugins is set to react, 
    // only jsx in .vue file will be parsed with vue jsx, 
    // jsx in other files will be parsed with react jsx
    veauryVitePlugins({
      type: 'react',
      // Configuration of @vitejs/plugin-vue
      // vueOptions: {...},
      // Configuration of @vitejs/plugin-react
      // reactOptions: {...}, 
      // Configuration of @vitejs/plugin-vue-jsx
      // vueJsxOptions: {...}
    })
  ]
})

如果想自定义vueJsx的编译作用域,可以通过设置type为custom来配置覆盖

import { defineConfig } from 'vite'
// >= veaury@2.1.1
import veauryVitePlugins from 'veaury/vite/index.js'

export default defineConfig({
  plugins: [
    veauryVitePlugins({
      type: 'custom',
      // The jsx in .vue files and in the directory named 'vue_app' will be parsed with vue jsx.
      vueJsxInclude: [/vue&type=script&lang\.[tj]sx?$/, /vue&type=script&setup=true&lang\.[tj]sx?$/, /[/\\]vue_app[\\/$]+/],
      // vueJsxExclude: [],
      // Configuration of @vitejs/plugin-vue
      // vueOptions: {...},
      // Configuration of @vitejs/plugin-react
      // reactOptions: {...}, 
      // Configuration of @vitejs/plugin-vue-jsx
      // vueJsxOptions: {...}
    })
  ]
})

5.具体使用

5.1 React 中的 Vue - 基本用法

import {applyVueInReact, applyPureVueInReact} from 'veaury'
// This is a Vue component
import BasicVueComponent from './Basic.vue'
import {useState} from 'react'
// Use HOC 'applyVueInReact'
const BasicWithNormal = applyVueInReact(BasicVueComponent)
// Use HOC 'applyPureVueInReact'
const BasicWithPure = applyPureVueInReact(BasicVueComponent)
export default function () {
  const [foo] = useState('Hello!')
  return <>
    <BasicWithNormal foo={foo}>
      <div>
        the default slot
      </div>
    </BasicWithNormal>
    <BasicWithPure foo={foo}>
      <div>
        the default slot
      </div>
    </BasicWithPure>
  </>
}

5.2 在 Vue 中使用React - 基本用法

推荐使用 applyPureReactInVue。

<template>
  <BasicPure :foo="foo">
    <div>
      the children
    </div>
  </BasicPure>
</template>
<script>
import {applyReactInVue, applyPureReactInVue} from 'veaury'
// This is a React component
import BasicReactComponent from './react_app/Basic.jsx'
import {ref} from 'vue'

export default {
  components: {
    // Use HOC 'applyReactInVue' or 'applyPureReactInVue'
    Basic: applyReactInVue(BasicReactComponent), 
    BasicPure: applyPureReactInVue(BasicReactComponent)
  },
  setup() {
    return {
      foo: ref('Hello!')
    }
  }
}
</script>

5.3 React 中的 Vue - 事件的使用

import {applyVueInReact} from 'veaury'
import BasicVue from './Basic.vue'
import {useState} from 'react'

const Basic = applyVueInReact(BasicVue)
export default function () {
  function onClickForVue() {
    console.log('clicked!')
  }

  return <div>
    {/*Trigger with $emit('click') in Vue component*/}
    <Basic onClick={onClickForVue}/>
  </div>
}

5.4 Vue 中的 React - 事件的使用

<template>
  <!-- Trigger with 'props.onClick()' in React component -->
  <ReactButton @click="onClickForReact"/>
</template>

<script>
import {ref} from 'vue'
import {applyPureReactInVue} from 'veaury'
// This is a React Component
import ReactButton from "./react_app/Button.jsx"

export default {
  components: {
    ReactButton: applyPureReactInVue(ReactButton)
  },
  setup() {
    function onClickForReact() {
      console.log('clicked!')
    }

    return {
      onClickForReact,
    }
  }
}
</script>

5.5 React 中的 Vue - slot的使用

'slots'的用法类似于Vue的jsx的'v-slots'的用法。

import {applyVueInReact} from 'veaury'
import BasicVue from './Basic.vue'

const Basic = applyVueInReact(BasicVue)
export default function () {
  return <div>
    {/*just send children*/}
    <Basic>
      {/* Render with '<slot/>' in Vue Component */}
      <div>this is children</div>
    </Basic>
    {/*send v-slots*/}
    <Basic v-slots={{
      // Render with '<slot name="slot1" />' in Vue Component
      slot1: <div>this is slot1(namedSlot)</div>,
      // Render with '<slot name="slot2" value="xxxxxx"/>' in Vue Component
      slot2: ({value}) => <div>this is slot2(scopedSlot), and receive value: {value}</div>,
      // Render with '<slot/>' in Vue Component
      default: <div>this is children</div>
    }}/>
    {/*another usage*/}
    <Basic>
      {{
        slot1: <div>this is slot1(namedSlot)</div>,
        slot2: ({value}) => <div>this is slot2(scopedSlot), and receive value: {value}</div>,
        default: <div>this is children</div>
      }}
    </Basic>
  </div>
}

5.6 React in Vue - render props 和 React 节点的使用

<template>
  <Basic>
    <!--  Render with 'props.slot1()' in React component  -->
    <template v-slot:slot1>
      <div>
        this is slot1 (render props)
      </div>
    </template>
    <!--  Render with 'props.slot2("xxxxx")' in React component  -->
    <template v-slot:slot2="bar">
      <div>
        this is slot2 (render props)<br/>
        this content is passed from React: {{bar}}
      </div>
    </template>
    <!--  Render with 'props.slot3' in React component  -->
    <template v-slot:node:slot3>
      <div>
        this is slot3 (react node)
      </div>
    </template>
    <!--  Render with 'props.children' in React component  -->
    <div>
      this is children (react node)
    </div>
  </Basic>
</template>

<script>
import {applyPureReactInVue} from 'veaury'
// This is a React Component
import ReactBasic from "./react_app/Slots.jsx"

export default {
  components: {
    Basic: applyPureReactInVue(ReactBasic)
  }
}
</script>

6.总结

本文主要向大家介绍了一个在Vue3中使用React,在React中使用Vue的一个全新的库veaury。关于库的更多用法本文不再深入展开,可以阅读文末的参考资料即可。但是从Github的数据看来,这个库当前还处于起步阶段,但是值得持续关注。


参考资料

https://github.com/devilwjp/veaury

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表