x6 react 最佳实际
提供一个 react 下应用 X6 的最佳范本:
- 简略易用,易于做逻辑拆分
- 体积小 (gzip 压缩后小于 0.5k)
- 反对多实例
- 反对应用 ref 绑定 x6 graph
装置
npm install react-x6-graph
yarn add react-x6-graph
设计
-
定义画布组件
// 应用 GraphContext 存储理论的 x6 graph 对象 const GraphContext = createContext() // 导出一个 Graph 组件,反对父组件传递 ref 拿到 graph 对象 export const Graph = forwardRef((props, ref) => {const [graph, setGraph] = useState(null) const realRef = ref || createRef() const {container, children, ...other} = props // 如果传递了 container,就应用传进来的 container 初始化画布 // 否则组件本人渲染一个 div 来初始化画布 const containerRef = createRef(container) useEffect(() => {if (containerRef.current && !realRef.current) { const graph = new X6.Graph({ container: containerRef.current, ...other, }) setGraph(realRef.current = graph) } }, []) return (<GraphContext.Provider value={graph}> {containerRef.current ? null : <div ref={containerRef} />} {!!graph && children} </GraphContext.Provider> ) }) // 导出一个帮忙函数以便 Graph 组件的子组件获取 x6 graph 对象 export const useGraphInstance = () => useContext(GraphContext)
-
应用
import {Graph, useGraphInstance} from 'react-x6-graph' const GraphBehavior = () => {const graph = useGraphInstance() // TODO 这里拿到 graph 对象解决本人的逻辑(例如应用后端数据初始化画布,减少事件监听...)return null } const GraphAddButton = () => {const graph = useGraphInstance() const [count, setCount] = useState(0) const addNode = useCallback(() => {// TODO 点击的时候增加节点并计数}, [count, graph]) return <Button type="primary"> 增加节点: {count}</Button> } function App() {const gRef = useRef() useEffect(() => { // TODO 这里应用父组件的 ref 不便将 gRef 传递到与 Graph 以外的组件应用 console.log('ref', gRef) }, [gRef.current]) return ( <div className="App"> <Graph grid resizing snapline keyboard clipboard width={800} height={600}> <GraphBehavior /> <GraphAddButton /> </Graph> {/* 1. Graph 组件反对多实例;2. 父组件传递 ref */} <Graph grid width={800} height={600} ref={gRef}> <GraphAddButton /> </Graph> </div> ); }
TODO
- [] 应用 react 自定义组件(默认应用 Portal)
- [] 用这个封装的 Graph 实现官网流程图(或者间接实现 xflow 的流程图)