npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@smart-portal/react-bridge

v1.0.1

Published

Use Vue and React each other

Downloads

13

Readme

SmartPortal react-bridge

门户vue-react bridge能力


重要功能

  • 在react工程中可以直接使用 Vue3 组件
  • 同项目中的vue以及react组件的context是共享的,可以实现数据无框架感阻碍通信
  • 在react中可以使用vue的hooks,获取vue组件的上下文数据,比如vue-router、vuex,同时在vue组件也可以使用react的hooks,获取到react组件或者应用的上下文数据,比如react-router、provide、context等
  • 支持高阶纯净模式使用,转换后的组件的子组件不再会有一个附加的dom元素容器

安装

$ npm i @smart-portal/react-bridge -S

# 一般搭配SmartPortal其他模块一起使用
$ npm i @smart-portal/components @smart-portal/hooks @smart-portal/utils @smart-portal/react-bridge -S

用法

在React组件中使用Vue组件 - 基本用法

// SmartPortal组件
import { SmartPortalComponents } from "@smart-portal/utils/register/bridge";

export default function () {
  const notifyOptions = {
    schema: "General",
    type: "Notify",
    num: 1,
    props: {
      content:
        "关于进一步加强能力中台储备区举办科技成果日(第33、34、35期)的通知",
    },
  };

  // 组件所有事件回调
  const emitsEvent = ({ eventName, data }) => {
    console.log("事件回调:", eventName, data);
  };

  return (
    <>
      <SmartPortalComponents
        options={notifyOptions}
        onEmitsEvent={emitsEvent}
      />
    </>
  );
}

在React组件中使用Vue组件 - 使用业务项目系统手写的Vue组件

// SmartPortal组件
import { ApplyVueInReact } from "@smart-portal/utils/register/bridge";
// 业务项目vue组件
import BasicVueComponent from "./Basic.vue";
const BasicWithNormal = ApplyVueInReact(BasicVueComponent);

export default function () {
  return (
    <>
      <Basic />
    </>
  );
}

在React组件中使用Vue组件 - 事件的用法

// SmartPortal组件
import { ApplyVueInReact } from "@smart-portal/utils/register/bridge";
// 业务项目vue组件
import BasicVueComponent from "./Basic.vue";
import { useState } from "react";

const Basic = ApplyVueInReact(BasicVueComponent);
export default function () {
  function handleClickEvent() {
    console.log("clicked!")
  }

  function handleEmitsEvent() {
    console.log("事件回调")
  }

  return (
    <div>
      {/* 在Vue组件Basic中可以使用$emit('click')和$emit('emitsEvent')触发事件绑定的函数 */}
      <Basic onClick={handleClickEvent} onEmitsEvent={handleEmitsEvent} />
    </div>
  );
}

在React组件中使用Vue组件 - 插槽的用法

这个插槽的用法与Vue的jsx传递插槽的用法非常相似

// SmartPortal组件
import { ApplyVueInReact } from "@smart-portal/utils/register/bridge";
// 业务项目vue组件
import BasicVueComponent from "./Basic.vue";

const Basic = ApplyVueInReact(BasicVueComponent);
export default function () {
  const vSlots = {
    // 在Vue组件的template内使用'<slot name="slot1" />'进行渲染
    slot1: <div>this is slot1(namedSlot)</div>,
    // 在Vue组件的template内使用'<slot name="slot2" value="xxxxxx"/>'进行渲染
    slot2: ({ value }) => (
      <div>this is slot2(scopedSlot), and receive value: {value}</div>
    ),
    // 在Vue组件的template内使用'<slot/>'进行渲染
    default: <div>this is children</div>,
  };
  return (
    <div>
      {/* 只传递children */}
      <Basic>
        {/* 在Vue组件的template内使用'<slot/>'进行渲染 */}
        <div>this is children</div>
      </Basic>
      {/* 传递 v-slots */}
      <Basic v-slots={vSlots} />
      {/* 另一种用法 */}
      <Basic>{vSlots}</Basic>
    </div>
  );
}

Context(上下文)

@smart-portal/react-bridge 会判断如果一个组件的外层有同一个框架的组件存在,那么就会使用 React 的 Portal 或者 Vue 的 Teleport创建被高阶组件包装的目标组件,而不是每次都创建一个新的应用实例。

React组件使用Vue组件 - Provider / useContext 的用法

// SmartPortal组件
import { ApplyVueInReact } from "@smart-portal/utils/register/bridge";
// 业务项目vue组件
import BasicVueComponent from "./Basic.vue";
import { createContext, useContext } from "react";

const Basic = ApplyVueInReact(BasicVueComponent);
// 创建 React context 对象
const Context = createContext({});

// React子组件
function SubReactComponent() {
  // 获取 context 值
  const { name } = useContext(Context);
  return <div className="slot">bossName from Context: {name}</div>;
}

export default function () {
  // 设置 context 值
  return (
    <Context.Provider value={{ name: "God" }}>
      {/* Vue组件Basic */}
      <Basic>
        {/* 在Vue组件的children里, React子组件可以获得从外层Provider传入的context的值 */}
        <SubReactComponent />
      </Basic>
    </Context.Provider>
  );
}

在React组件中使用Vue组件, v-model / v-models 的用法

'v-model' 的用法与Vue的jsx中的'v-model'用法相似
在React jsx中使用 v-model 属性, 可以有如下格式:
[ modelValue, modelSetter, argumentKey, argumentModifiers ]
[ modelValue, modelSetter, argumentModifiers ]
[ modelValue, modelSetter ]
'argumentKey'代表了v-model的自定义参数名, 默认情况下, v-model的参数名时modelValue, 也可以将'argumentKey'设置在v-model属性之后的附加后缀上, 比如 v-model-god={[godValue, setGodValue]} = v-model={[godValue, setGodValue, 'god']}

// types
type modelValue = any;
type modelSetter = (newValue) => void;
type argumentKey = string;
type argumentModifiers = string[];
// SmartPortal组件
import { ApplyVueInReact } from "@smart-portal/utils/register/bridge";
// 业务项目vue组件
import BasicVue from "./Basic.vue";
import Basic1Vue from "./Basic1.vue";
import { useState } from "react";

const Basic = ApplyVueInReact(BasicVue);
const Basic1 = ApplyVueInReact(Basic1Vue);
export default function () {
  const [foo, setFoo] = useState(Math.random());
  const [bar, setBar] = useState(Math.random());
  const [zoo, setZoo] = useState(Math.random());

  return (
    <div>
      <Basic v-model={[foo, setFoo]} v-model-bar={[bar, setBar]} />
      {/*<Basic1 v-model={[zoo, setZoo, 'zoo']}/>*/}
      {/*<Basic1 v-model={[zoo, setZoo, 'zoo', ['number']]}/>*/}
      {/*<Basic1 v-model-zoo={[zoo, setZoo, ['number']]}/>*/}
      <Basic1
        v-models={{
          // v-models对象中的key设置为'modelValue'时, 等同于默认的v-model属性
          modelValue: [zoo, setZoo],
          //...可以设置其他的自定义v-model的key
        }}
      />
    </div>
  );
}

在React组件中使用Vue组件, 使用异步的Vue组件

import { lazyVueInReact, lazyPureVueInReact } from "@smart-portal/react-bridge";

const AsyncBasicWithNormal = lazyVueInReact(() => import("./Basic"));
const AsyncBasicWithPure = lazyPureVueInReact(() => import("./Basic"));
export default function () {
  return (
    <>
      <AsyncBasicWithNormal />
      <AsyncBasicWithPure />
    </>
  );
}
// types
type lazyReactInVue = (asyncImport: Promise<any>, options?: options) => any;

在React组件中使用Vue组件, 获取ref实例的用法

// SmartPortal组件
import { ApplyVueInReact } from "@smart-portal/utils/register/bridge";
import BasicVue from "./Basic.vue";
import React, { createRef, useEffect } from "react";

const Basic = ApplyVueInReact(BasicVue);
export default function () {
  const basicInstance = createRef(null);
  useEffect(() => {
    // Get the real vue instance through `__veauryVueRef__`
    console.log(basicInstance.current.__veauryVueRef__);
  }, []);
  return <Basic ref={basicInstance} />;
}

Vue 和 React共存时会引发JSX的TS类型错误.

如果您可以忽略 IDE 中的 TS 错误警告,则可以跳过本章。

Vue(@vue/runtime-dom) 和 React(@types/react) 都在全局命名空间 JSX 中扩展了类型接口,这会导致类型冲突。
例如,JSX.Element 不能同时扩展 ReactElement 和 VNode。
所以如果项目中同时安装了Vue和React,会在IDE(如vscode或webstorm)的JSX中引起TS错误警告,但这不会影响开发环境和生产环境的编译。
一个可行的解决方案是使用 patch-package 来修改 @vue/runtime-dom/dist/runtime-dom.d.ts@types/react/index.d.ts,并且确保在tsconfig.json中设置compilerOptions.jsxpreserve
比如这两个文件的改动如下。

node_modules/@types/react/index.d.ts(@types/[email protected])

diff --git a/node_modules/@types/react/index.d.ts b/node_modules/@types/react/index.d.ts
index 5c5d343..a850f38 100644
--- a/node_modules/@types/react/index.d.ts
+++ b/node_modules/@types/react/index.d.ts
@@ -3118,7 +3118,9 @@ type ReactManagedAttributes<C, P> = C extends { propTypes: infer T; defaultProps

 declare global {
     namespace JSX {
-        interface Element extends React.ReactElement<any, any> { }
+        interface Element extends React.ReactElement<any, any> {
+            [k: string]: any
+         }
         interface ElementClass extends React.Component<any> {
             render(): React.ReactNode;
         }
@@ -3133,8 +3135,12 @@ declare global {
                 : ReactManagedAttributes<T, P>
             : ReactManagedAttributes<C, P>;

-        interface IntrinsicAttributes extends React.Attributes { }
-        interface IntrinsicClassAttributes<T> extends React.ClassAttributes<T> { }
+        interface IntrinsicAttributes extends React.Attributes {
+            [k: string]: any
+         }
+        interface IntrinsicClassAttributes<T> extends React.ClassAttributes<T> {
+            [k: string]: any
+        }

         interface IntrinsicElements {
             // HTML

node_modules/@vue/runtime-dom/dist/runtime-dom.d.ts(@vue/[email protected])

diff --git a/node_modules/@vue/runtime-dom/dist/runtime-dom.d.ts b/node_modules/@vue/runtime-dom/dist/runtime-dom.d.ts
index 3366f5a..b9eacc6 100644
--- a/node_modules/@vue/runtime-dom/dist/runtime-dom.d.ts
+++ b/node_modules/@vue/runtime-dom/dist/runtime-dom.d.ts
@@ -1493,7 +1493,7 @@ type NativeElements = {

 declare global {
   namespace JSX {
-    interface Element extends VNode {}
+    // interface Element extends VNode {}
     interface ElementClass {
       $props: {}
     }