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

react-big-screen

v0.0.28

Published

一个前端大屏看板项目

Readme

React-Big-Screen

react-big-screen 是一个使用React开发的前端可拖拽大屏开源项目,通过简单的拖拽和配置即可搭建页面。本项目已经实现了大部分的核心功能,包括:拖拽系统、多页面管理、组件联动、远程组件、预览页等(详见下文)。

页面截图

编辑:

预览:

核心功能

详见掘金专栏前端大屏原理系列

  • ✅ 拖拽系统。
  • ✅ 成组、取消成组
  • ✅ 鼠标范围框选
  • ✅ 右键菜单
  • ✅ 快捷键
  • ✅ 多组件联动
  • ✅ 多页面管理
  • ✅ 自定义组件
  • ✅ 自定义属性面板
  • ✅ 自适应预览页
  • ✅ 容器组件
  • ✅ 加载远程组件
  • ✅ i18n国际化
  • ✅ 可撤销历史记录
  • ✅ 导入、导出文件

功能 demo

快速开始

注:仅支持node版本20+、react版本18+

pnpm install react-big-screen
// index.tsx
import { EXAMPLE, RbsEngine } from "react-big-screen";
import * as React from "react";
import "antd/dist/antd.min.css";
import "react-big-screen/es/style.css";

export default () => {
  const domRef = React.useRef<HTMLDivElement>(null);

  React.useEffect(() => {
    const engine = new RbsEngine();
    
    // 挂载到DOM
    engine.mount(domRef.current!).then(() => {
      // 挂载成功后,导入JSON文件
      engine.importJSON(EXAMPLE.classic);
    });
    
    // 销毁
    return () => {
      engine.destroy()
    };
  }, []);

  return (
    <div
      ref={domRef}
      style={{
        width: "100vw",
        height: "100vh",
        position: "fixed",
        overflow: "hidden",
      }}
    />
  );
};

本地调试

本地启动一个项目,用以调试或者开发功能。

# 拉取代码
git clone https://github.com/tangjiahui-cn/react-big-screen.git 

# 进入目录
cd react-big-screen

# 安装依赖
# [email protected][email protected] (或:[email protected][email protected])
pnpm i

# 本地运行
pnpm dev

在线预览:https://tangjiahui-cn.github.io/react-big-screen

创建一个自定义组件

开发自定义组件,只需要3步:

  • 创建渲染组件 Component
  • 创建属性配置组件 Attributes
  • 注册自定义组件对象。

1. 创建 Component

使用内置的createComponent创建自定义组件,可以享受编辑器类型提示。

import engine, { createComponent } from '@/engine';

// 配置属性值类型
interface Options {
  value: string; // 显示内容
}

const Component = createComponent<Options>(props => {
  const { options, width, height } = props;
  return (
    <div style={{ width, height }}>
      {options?.value}
    </div>
  )
})

2. 创建Attributes

创建属性配置组件,可以使用createAttributescreateAttributesByConfig。(推荐使用createAttributesByConfig,享受更高效的表单配置式开发)

// 使用 createAttributes
import engine, { createAttributes } from '@/engine';

// 属性配置组件
const Attributes = createAttributes<Options>(props => {
  const { options, onChange } = props;
  return (
    <div>
      <span>显示内容:</span>
      <input
        value={options?.value}
        onChange={e => onChange({ value: e.target.value })}
        maxLength={100}
      />
    </div>
  )
})
// 使用 createAttributesByConfig
import engine, { createAttributesByConfig } from '@/engine';

export default createAttributesByConfig<Options>(
  [
    {
      key: "value",
      label: "显示内容",
      component: "input",
      options: {
        maxLength: 100
      },
    },
  ]
);

3. 注册组件

// 注册组件
engine.component.register({
  cId: 'demo-text', // 组件id(必填、唯一)
  cName: 'demo-文字', // 组件名称
  x: 0, // 初始 x
  y: 0, // 初始 y
  width: 200, // 初始宽度
  height: 32, // 初始高度
  component: Component, // 模板组件
  attributesComponent: Attributes, // 属性配置组件
})

创建一个容器组件

容器组件:一个移动时会同时改变所有关联组件位置的组件。

1. 注册容器组件

创建一个容器组件,创建Component创建Attributes和普通组件一样,仅需要修改注册对象。

只要注册对象panels属性有值,就被认为是一个容器组件。运行时若有组件挂载到该容器,则会设置挂载组件的 panelId 为 该容器组件的currentPanelId。(注意:panelId为引擎自动绑定请不要修改!)

  • panels:当前容器组件所包含的全部面板(panel是容器的一个面板)。
  • currentPanelId:当前容器组件展示的面板 panel 的 id。
  • panelId: 所属父容器 panels 中某个面板的id。

挂载 / 卸载面板 api:

  • engine.componentNode.hidePanel:隐藏一个面板全部子组件
  • engine.componentNode.showPanel:显示一个面板全部子组件
// 单面板容器组件
engine.component.register({
  // ...
  // 只要包含 panels 属性就被认为是一个容器组件
  // (value值由引擎自动生成,此处置空)
  panels: [{ label: "特殊卡片", value: "" }],
})
// 多面板容器组件
engine.component.register({
  // ...
  // 只要包含 panels 属性就被认为是一个容器组件
  // (value值由引擎自动生成,此处置空)
  panels: [
    { label: "面板一", value: "" },
    { label: "面板二", value: "" },
    { label: "面板三", value: "" },
  ],
})

2. 运行时切换面板

/**
 * 点击按钮切换面板
 */
import engine, { createComponent } from '@/engine';
import { useEffect, useRef } from "react";

const Component = createComponent<Options>(props => {
  const { options, width, height, componentNode } = props;
  const lastPanelId = useRef()

  // 切换面板
  function handleChange(panelId) {
    if (!panelId || lastPanelId.current === panelId) return;
    // 先隐藏上一个panel的所有组件
    engine.componentNode.hidePanel(lastPanelId.current);
    // 再显示当前panel的组件
    engine.componentNode.showPanel(lastPanelId.current = panelId);
  }

  // 其他组件控制切换
  useEffect(() => {
    handleChange(componentNode?.currentPanelId)
  }, [componentNode?.currentPanelId])

  return (
    <div style={{ width, height }}>
      {componentNode?.panels?.map?.(panel => {
        return (
          <button
            key={panel?.value}
            onClick={() => handleChange(panel?.value)}
          >
            {panel?.label}
          </button>
        )
      })}
    </div>
  )
})

性能优化

(1) 组件独立更新

每个组件更新时,只会更新当前渲染节点,而不会更新所有组件。

(2) 拖拽优化

单个或多个组件拖拽过程中,实时修改对应dom的位置,拖拽结束才会保存生效变更范围内的组件。

(3) 隐藏组件不渲染

有些不显示的组件,例如处于容器中、或者show设置false等,不会在页面上渲染。等到外界控制其显示时,局部更新其节点重新渲染,而不会影响所有组件。

(4) 远程组件包优化

组件包下载后,源码存储在浏览器端IndexedDB中,不会占用内存。下载时,才会从浏览器存储中取出。

(5) vite 构建优化

手动分包,将monaco-editor等固定不变的大型包单独划分chunk便于更好的利用缓存。 一些随着按需加载体积不断增大的包单独划分(例如:antdahooks等),避免每次改动都更新其他未修改包。

(6) 按需加载

同时nginx设置gzip,体积可再次减小75%

常见库替换:

  • dayjs:代替moment。
  • lodash-es:代替lodash。

大型库按需加载:

  • echarts:减小 46%。1050kb => 570kb。
  • monoco-editor:减小 36%。3600kb => 2308kb。

(7) 使用“事件委托”实现拖拽

在编辑器容器处监听mouse事件,通过dom.dataset.id获取实例的一切信息,并借此实现组件移动、放置layout、范围框选中等。无需创建实例数量的事件监听器,节省内存提高性能。

(8) 合并事件

一个事件同时运行多个功能。例如 startMove 支持 hookQueue,一次点击流程(mousedown -> mouseup),即可依次运行每个功能注册的回调函数,无需拖拽实例、选中实例功能各自创建一个mousedown的事件监听。

(9) 异步组件

componentattributesComponent 支持传入React.lazy(() => import("./...") 形式,以支持异步组件,减小首屏加载包体积。

...

dom 事件

点击事件只涉及到: clickmousedownmousemovemouseup

多组件联动

自己单独实现了一套事件机制。component中声明了暴露事件列表exposes、触发事件列表triggers

  • exposes 是暴露给外界,用来调用内部事件的端口。
  • triggers 是声明内部可以触发的事件,用来在 [属性面板-交互] 中读取该列表进行配置与其他组件联动。

关于组件内部使用?

props 中获取 useExposehandleTrigger。通过 useExpose 去定义运行时暴露的事件行为,handleTrigger 去触发内部事件的执行。

多页面管理

多页面,主要适用于一个大屏多个子页面的场景。

展示一个页面时,其他页面会卸载,不渲染而只保留数据,因此不会造成性能损失。

若要控制多页面切换,需要开发导航组件

  • usePages:实时获取所有页面
  • useCurrentPageId: 获取当前页id
  • selectPage: 选中对应页面(即切换页面)

常见场景:

  • 单大屏多子页面:顶部的导航栏tabs,点击打开目标子页面。
  • 类SPA站点:头部面包屑导航,点击跳转对应页面。
  • 单页面文档站点:导航下拉框,快速打开对应文档页。

为什么会出现子页面,容器组件难道不行吗? 答:子页面会完整的加载、卸载、刷新一个页面的全部组件,而容器包含的所有组件一直存在(只会随页面卸载而删除)。

设计复杂页面

若要实现复杂页面,则需将页面元素抽象成 一个个的实例,多个实例通过暴露事件触发事件相互沟通。

react-big-screen 中,事件机制是一个十分重要的功能,甚至可以触发自身的 暴露事件!

例如:设计一个中后台查询表格页。我们只需要准备按钮表格,点击 按钮 触发表格暴露的 查询 事件即可。如果想要修改查询参数,则只需要设置解析函数。

另外,有时候会用到多页面管理,在一个页面中支持切换多个子页面。 可以单独开发 导航组件,用于管理页面的切换、或当做路由面包屑等。

远程组件

通过远程组件功能,可以拥有个人资产。

src/common-module.ts 文件中配置公共模块配置,以此减小远程组件包体积。

加载方式:

  • 本地上传
  • 远程URL

支持格式:

  • 支持 UMD 模块包。
  • 支持 AMD 模块包。
  • 支持 .zip 压缩包。