fix: Watcher not re-binding when initialized with empty arr

This commit is contained in:
Braks
2022-04-24 13:34:22 +02:00
parent bb30db7c08
commit f69118e265
2 changed files with 52 additions and 46 deletions
+4 -2
View File
@@ -28,11 +28,13 @@ const props = withDefaults(defineProps<FlowProps>(), {
const emit = defineEmits([...Object.keys(createHooks()), 'update:modelValue', 'update:nodes', 'update:edges']) const emit = defineEmits([...Object.keys(createHooks()), 'update:modelValue', 'update:nodes', 'update:edges'])
const modelProps = useVModels(props, emit) const modelValue = useVModel(props, 'modelValue', emit)
const modelNodes = useVModel(props, 'nodes', emit)
const modelEdges = useVModel(props, 'edges', emit)
const { id, hooks, getNodeTypes, getEdgeTypes, ...rest } = useVueFlow() const { id, hooks, getNodeTypes, getEdgeTypes, ...rest } = useVueFlow()
const dispose = useWatch(modelProps, { id, hooks, getNodeTypes, getEdgeTypes, ...rest }) const dispose = useWatch({ modelValue, nodes: modelNodes, edges: modelEdges }, props,{ id, hooks, getNodeTypes, getEdgeTypes, ...rest })
onUnmounted(() => { onUnmounted(() => {
dispose() dispose()
+48 -44
View File
@@ -1,9 +1,9 @@
import { Ref, ToRefs } from 'vue' import { Ref, ToRefs } from 'vue'
import { WatchPausableReturn } from '@vueuse/core' import { WatchPausableReturn } from '@vueuse/core'
import { FlowProps, VueFlowStore } from '~/types' import { FlowProps, GraphEdge, GraphNode, VueFlowStore } from '~/types'
const isDef = <T>(val: T): val is NonNullable<T> => typeof val !== 'undefined' const isDef = <T>(val: T): val is NonNullable<T> => typeof val !== 'undefined'
export default (models: ToRefs<FlowProps>, store: VueFlowStore) => { export default (models: ToRefs<Pick<FlowProps, 'nodes' | 'edges' | 'modelValue'>>, props: FlowProps, store: VueFlowStore) => {
const scope = effectScope() const scope = effectScope()
scope.run(() => { scope.run(() => {
@@ -23,11 +23,12 @@ export default (models: ToRefs<FlowProps>, store: VueFlowStore) => {
store.setElements(v) store.setElements(v)
pauseStore = watchPausable( pauseStore = watchPausable(
[() => store.edges.value.length, () => store.nodes.value.length], [store.edges, store.nodes, () => store.edges.value.length, () => store.nodes.value.length],
() => { ([e, n]) => {
models.modelValue!.value = [...store.nodes.value, ...store.edges.value] const val = [...(n as GraphNode[]), ...(e as GraphEdge[])]
if (val.length) models.modelValue!.value = val
}, },
{ immediate: true }, { immediate: true, flush: 'post' },
) )
nextTick(() => { nextTick(() => {
@@ -58,7 +59,9 @@ export default (models: ToRefs<FlowProps>, store: VueFlowStore) => {
pauseStore = watchPausable( pauseStore = watchPausable(
() => store.nodes.value.length, () => store.nodes.value.length,
() => (models.nodes!.value = [...store.nodes.value]), () => {
if (store.nodes.value.length) models.nodes!.value = [...store.nodes.value]
},
{ immediate: true }, { immediate: true },
) )
@@ -90,7 +93,9 @@ export default (models: ToRefs<FlowProps>, store: VueFlowStore) => {
pauseStore = watchPausable( pauseStore = watchPausable(
() => store.edges.value.length, () => store.edges.value.length,
() => (models.edges!.value = [...store.edges.value]), () => {
if (store.edges.value.length) models.edges!.value = [...store.edges.value]
},
{ immediate: true }, { immediate: true },
) )
@@ -108,13 +113,13 @@ export default (models: ToRefs<FlowProps>, store: VueFlowStore) => {
const watchMaxZoom = () => { const watchMaxZoom = () => {
scope.run(() => { scope.run(() => {
watch( watch(
[() => models.maxZoom, models.maxZoom], () => props.maxZoom,
() => { () => {
if (models.maxZoom && isDef(models.maxZoom.value)) { if (props.maxZoom && isDef(props.maxZoom)) {
store.setMaxZoom(models.maxZoom.value) store.setMaxZoom(props.maxZoom)
} }
}, },
{ immediate: isDef(models.maxZoom?.value) }, { immediate: isDef(props.maxZoom) },
) )
}) })
} }
@@ -122,13 +127,13 @@ export default (models: ToRefs<FlowProps>, store: VueFlowStore) => {
const watchMinZoom = () => { const watchMinZoom = () => {
scope.run(() => { scope.run(() => {
watch( watch(
[() => models.minZoom, models.minZoom], () => props.minZoom,
() => { () => {
if (models.minZoom && isDef(models.minZoom.value)) { if (props.minZoom && isDef(props.minZoom)) {
store.setMinZoom(models.minZoom.value) store.setMinZoom(props.minZoom)
} }
}, },
{ immediate: isDef(models.minZoom?.value) }, { immediate: isDef(props.minZoom) },
) )
}) })
} }
@@ -136,13 +141,13 @@ export default (models: ToRefs<FlowProps>, store: VueFlowStore) => {
const watchApplyDefault = () => { const watchApplyDefault = () => {
scope.run(() => { scope.run(() => {
watch( watch(
[() => models.applyDefault, models.applyDefault], () => props.applyDefault,
() => { () => {
if (models.applyDefault && isDef(models.applyDefault.value)) { if (props.applyDefault && isDef(props.applyDefault)) {
store.applyDefault.value = models.applyDefault.value store.applyDefault.value = props.applyDefault
} }
}, },
{ immediate: isDef(models.applyDefault?.value) }, { immediate: isDef(props.applyDefault) },
) )
watch( watch(
@@ -158,32 +163,31 @@ export default (models: ToRefs<FlowProps>, store: VueFlowStore) => {
}) })
} }
watchModelValue() const watchRest = () => {
watchNodesValue() const skip = ['id', 'modelValue', 'edges', 'nodes', 'maxZoom', 'minZoom', 'applyDefault']
watchEdgesValue() Object.keys(props).forEach((prop) => {
watchMaxZoom() if (!skip.includes(prop)) {
watchMinZoom() const model = props[prop as keyof typeof props]
watchApplyDefault() const storedValue = (<any>store)[prop] as Ref
const skip = ['id', 'modelValue', 'edges', 'nodes', 'maxZoom', 'minZoom', 'applyDefault'] scope.run(() => {
Object.keys(models).forEach((m) => { watch(
if (!skip.includes(m)) { () => model,
const model = models[m as keyof typeof models] () => {
const storedValue = (<any>store)[m] as Ref if (model && isDef(model)) {
storedValue.value = model
}
},
{ immediate: isDef(model) },
)
})
}
})
}
scope.run(() => { ;[watchModelValue, watchNodesValue, watchEdgesValue, watchMinZoom, watchMaxZoom, watchApplyDefault, watchRest].forEach(
watch( (watch) => watch(),
[() => model, model], )
() => {
if (model && isDef(model.value)) {
storedValue.value = model.value
}
},
{ immediate: isDef(model?.value) },
)
})
}
})
}) })
return () => scope.stop() return () => scope.stop()