@antv/x6-vue-shape
Version:
X6 shape for rendering vue components.
125 lines (112 loc) • 2.94 kB
text/typescript
import { NodeView, Dom, Node } from '@antv/x6'
import { isVue2, isVue3, createApp, h, Vue2 } from 'vue-demi'
import { shapeMaps } from './registry'
import { isActive, connect, disconnect } from './teleport'
export class VueShapeView extends NodeView<Node> {
static action = 'vue' as any
private vm: any
getComponentContainer() {
return this.selectors && (this.selectors.foContent as HTMLDivElement)
}
confirmUpdate(flag: number) {
const ret = super.confirmUpdate(flag)
return this.handleAction(ret, VueShapeView.action, () => {
this.renderVueComponent()
})
}
protected targetId() {
return `${this.graph.view.cid}:${this.cell.id}`
}
protected renderVueComponent() {
this.unmountVueComponent()
const root = this.getComponentContainer()
const node = this.cell
const graph = this.graph
if (root) {
const { component } = shapeMaps[node.shape]
if (component) {
if (isVue2) {
const Vue = Vue2 as any
this.vm = new Vue({
el: root,
render(h: any) {
return h(component, { node, graph })
},
provide() {
return {
getNode: () => node,
getGraph: () => graph,
}
},
})
} else if (isVue3) {
if (isActive()) {
connect(this.targetId(), component, root, node, graph)
} else {
this.vm = createApp({
render() {
return h(component, { node, graph })
},
provide() {
return {
getNode: () => node,
getGraph: () => graph,
}
},
})
this.vm.mount(root)
}
}
}
}
}
protected unmountVueComponent() {
const root = this.getComponentContainer()
if (this.vm) {
isVue2 && this.vm.$destroy()
isVue3 && this.vm.unmount()
this.vm = null
}
if (root) {
root.innerHTML = ''
}
return root
}
onMouseDown(e: Dom.MouseDownEvent, x: number, y: number) {
const target = e.target as Element
const tagName = target.tagName.toLowerCase()
if (tagName === 'input') {
const type = target.getAttribute('type')
if (
type == null ||
[
'text',
'password',
'number',
'email',
'search',
'tel',
'url',
].includes(type)
) {
return
}
}
super.onMouseDown(e, x, y)
}
unmount() {
if (isActive()) {
disconnect(this.targetId())
}
this.unmountVueComponent()
super.unmount()
return this
}
}
VueShapeView.config({
bootstrap: [VueShapeView.action],
actions: {
component: VueShapeView.action,
},
})
NodeView.registry.register('vue-shape-view', VueShapeView, true)