开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情
👋🏻 嗨,这里是月光多晴朗
的日常频道🛰开源探月
。
jsoncrack.com—json可视化工具
上篇说过了jsoncrack
的几个页面、css in js
和漂亮的封装,这篇就真的来看看核心代码了。
值得一看的无非两处:左边的JSON文本编辑器,和右边的画布。
Monaco
编辑器
本项目中的编辑器使用的是开源的@monaco-editor/react
,另外做了一个加载错误的兜底,当Monaco
抛出异常时进行提示。根据本项目的使用体验来说,Monaco
编辑器还是很好用的。
export const JsonEditor: React.FC = () => {
const [hasError, setHasError] = React.useState(false);
return (
<StyledEditorWrapper>
<ErrorContainer hasError={hasError} />
<MonacoEditor setHasError={setHasError} />
</StyledEditorWrapper>
);
};
至于编辑器内部的逻辑,这次先不细看了,但是可以挖个坑给这个大坑,下次一定。
reaflow
画布绘制
本项目中画布的基础功能还是比较完善的:如缩放、移动、自适应、触摸板手势、导出图片等,操作体验也很流畅。另外,也有一些交互动效:如节点和边的hover效果、节点点击事件(边目前没有点击事件)。其中节点也分为了两个区域:
节点主体(展示对象信息或类型为列表的字段名)和右侧子节点展开按钮。
当节点为对象时,只展示节点主体,而对象中列表类型的字段则会被处理为对象节点的下级节点。列表字段的节点则包含节点主体和子节点展开收起按钮,可以控制子节点的显示或隐藏。
整个画布的底层绘制依赖于reaflow
,其使用非常便捷。
REAFLOW is a modular diagram engine for build static or interactive editors. The library is feature rich and modular allowing for displaying complex visualizations with total customizability.
谷歌翻译:REAFLOW 是用于构建静态或交互式编辑器的模块化图表引擎。该库功能丰富且模块化,允许显示具有完全可定制性的复杂可视化。
可以看一个demo,这也是本项目中使用reaflow
的方法。
import React from 'react';
import { Canvas } from 'reaflow';
const nodes = [
{
id: '1',
text: '1'
},
{
id: '2',
text: '2'
}
];
const edges = [
{
id: '1-2',
from: '1',
to: '2'
}
];
export const MyDiagram = () => (
<Canvas
nodes={nodes}
edges={edges}
/>
);
绘制结果:
当然,并非所有的画布能力都由它提供。尽管reaflow
中有缩放方法,但本项目中禁用了它,选择了react-zoom-pan-pinch
包提供的缩放能力。
Storybook
组件框架
有趣的是,reaflow
和react-zoom-pan-pinch
的文档都是使用Storybook
搭建的。
Storybook is a frontend workshop for building UI components and pages in isolation. Thousands of teams use it for UI development, testing, and documentation. It’s open source and free.
谷歌翻译:Storybook 是一个前端工作室,用于单独构建 UI 组件和页面。数以千计的团队使用它进行 UI 开发、测试和文档编制。它是开源且免费的。
通过Storybook
,可以进行UI组件的开发、测试、文档编写(几乎是全方位了),是“组件驱动开发”的重要工具。同类工具中,还有Docz
、React Styleguidist
、UMI
构建体系下的dumi
等。就笔者个人而言,因为工作原因,对dumi
的使用会相对更多。
Storybook
在其中应该算是“全能大哥大型”了。它有着75K+Star,支持多种技术栈,社区活跃,文档接口丰富…… 大型的项目很是值得一试,至于小项目的体量是否能承受它的学习成本就不一定啦。
数据管理
上面只是个题外话。
回到我们的核心页面。左边的编辑器也看过了,右边的画布渲染也瞧过了,那二者之间的数据是如何解析和传递的呢?
答案也很简单:zustand
。
zustand
状态管理
redux
看太多了,有点不太认识其他的状态管理工具了。
A small, fast and scalable bearbones state-management solution using simplified flux principles. Has a comfy api based on hooks, isn’t boilerplatey or opinionated.
Don’t disregard it because it’s cute. It has quite the claws, lots of time was spent to deal with common pitfalls, like the dreaded zombie child problem, react concurrency, and context loss between mixed renderers. It may be the one state-manager in the React space that gets all of these right.
使用简化的通量原理的小型、快速和可扩展的 bearbones 状态管理解决方案。 有一个基于hooks的舒适api,不是样板文件或固执己见。
不要因为它可爱而忽视它。 它有很多爪子,花了很多时间来处理常见的陷阱,比如可怕的僵尸子问题、反应并发和混合渲染器之间的上下文丢失。 它可能是 React 空间中的唯一状态管理器,可以正确处理所有这些问题。
zustand
基于hooks使用,看起来使用体验比redux
要轻量不少。
import create from 'zustand'
const useBearStore = create((set) => ({
bears: 0,
increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
removeAllBears: () => set({ bears: 0 }),
}))
的确,看看官方给出的优于redux
的理由,就会发现轻量就是原因之一:
Why zustand over redux?
- Simple and un-opinionated
- Makes hooks the primary means of consuming state
- Doesn’t wrap your app in context providers
- Can inform components transiently (without causing render)
为什么 zustand 而不是 redux?
- 简单而不固执己见
- 使钩子成为消费状态的主要方式
- 不将您的应用包装在上下文提供程序中
- 可以瞬时通知组件(不会导致渲染)
数据流
项目中共有三个状态文件:
src/store
├── useConfig.tsx
├── useGraph.tsx
└── useStored.tsx
从核心数据流来看,useConfig
中存储了用户输入的json
数据、useGraph
中存储了nodes
和edges
数据、useStored
则与此无关。
用户输入的数据通过json
编辑器组件更新到useConfig
中的json
。
从json
到nodes
和edges
,则是在json
编辑器组件和widget
组件(昨天说到的iframe小窗模式,此时没有json
编辑器)中,对useConfig
中json
的变化实时监听,并更新到useGraph
中的nodes
和edges
。而这一过程的数据处理逻辑则单独封装在src/utils/jsonParser
的parse
方法中,具体实现还是有些复杂,300+行代码,感兴趣可以自己扒拉看一看。
最后,简单用时序图画了一下这个过程。
sequenceDiagram
participant User
participant Editor
participant Widget
User->>Editor: update JSON
Editor->>useConfig: update JSON
useConfig-->>Editor: JSON updated
useConfig-->>Widget: JSON updated
Editor->>useGraph: update nodes
Editor->>useGraph: update edges
Widget->>useGraph: update nodes
Widget->>useGraph: update edges
useGraph->>Canvas: nodes updated
useGraph->>Canvas: edges updated
Canvas-->>Canvas: update canvas
这就是本项目核心功能的数据流啦,顺便复习一下时序图吧!(大雾)
小小的开源项目,还藏着不少有趣的工具和逻辑!
今天就看到这里,赶紧👍🏻三连 + 👀关注
明天继续!
欢迎关注公众号:开源探月
,一起寻宝 🏴☠️
欢迎✨Star
:GitHub原文
暂无评论内容