lloydzhou / X6

🚀 JavaScript diagramming library that uses SVG and HTML for rendering.
https://x6.antv.vision
MIT License
0 stars 0 forks source link

x6的一些思考 #1

Open lloydzhou opened 2 years ago

lloydzhou commented 2 years ago
  1. 是否考虑引入更优秀的前端框架(vue/react/preact/svelte/lit-html)处理渲染逻辑,大多数的前端框架都会利用vdom以提升渲染性能
  2. 是否考虑引入性能更好的第三方库操作svg,类似(raphael/svg.js/two.js/d3.js ...)
  3. 自定义组件:考虑参考qiankun(实际上是single-spa)的设计,不管用户自己想要用什么方式自定义节点,只需要导出几个固定的生命周期钩子即可。
lloydzhou commented 2 years ago
const useProtal = (() => {
  let instance: any = {}
  return function() {
    // 使用单例模式
    if (instance.connect) {
      return instance
    }
    const Portal = () => {
      const [items, setItems] = useState<{id: string, portal: React.ReactPortal}[]>([])
      instance.connect = useCallback((id: string, portal: React.ReactPortal) => {
        setItems([...items, {id, portal}])
      }, [items])
      instance.disconnect = useCallback((id: string) => {
        setItems(items.filter(i => i.id !== id))
      }, [items])
      return (<div id="protal">{items.map(item => item.portal)}</div>)
    }
    instance.Portal = Portal
    instance.wrap = (Component: any) => ({
      mount: async (props: any) => {
        const { graph, node, container } = props
        // 这里使用graph.view.id做前缀
        const id = `${graph.view.id}:${node.view.id}`
        instance.connect(id, ReactDOM.createPortal(<Component {...props} />, container))
      },
      unmount: async (props: any) => {
        const { graph, node } = props
        const id = `${graph.view.id}:${node.view.id}`
        instance.disconnect(id)
      }
    })
    return instance
  }
})();

const portal = useProtal()

const { Portal } = portal

    const TestComponent = (props: any) => {
      const { node } = props
      const [num, setNum] = useState(0)
      node.on('change:data', () => {
        setNum(node.getData().num)
      })
      const inc = useCallback(() => {
        node.setData({ num: num + 1 })
      }, [num, node])
      return (
        <Button size="small" onClick={inc}>
          Antd Button {num}
        </Button>
      )
    }

    const target3 = graph.addNode({
      x: 680,
      y: 100,
      width: 100,
      height: 40,
      shape: 'html',
      html: portal.wrap(TestComponent),
    })