I have a Vue component that recursively generates a tree recursively with a <CustomTreeNode>
component. It looks something like this:
<template>
<div>
<div>
<span @click="nodeClicked($event, localValue)">
{{ localValue.name }}
</span>
</div>
<div v-if="open && value.children.length > 0">
<!-- recursive component -->
<CustomTreeNode
v-for="citem in localValue.children"
:key="citem.id"
:value="citem"
:selected="citem.selected"
@node-clicked="nodeClicked($event, citem)"
/>
</div>
</div>
</template>
The handler on the TreeNode component emits the event, which is in turned handled by the page hosting the Tree.
const nodeClicked = (e: Event, node: ITreeNode) => {
console.log(`KTREENODE: nodeClicked() called with item ${node.name}`) // <------- always invoked
emit('node-clicked', [e, node]) // <<-------- only invoked for root nodes, not children
console.log(` KETREENODE: after emit() called after [${node.name}] node clicked`)
}
The tree renders just fine, and when I click on a top-level node the events are passed up
to the host and I can manage. In the handler for the node-clicked
event in parent <CustomTree>
component and its host. HOWEVER, when I click on a child item, the nodeClicked
event handler method is called, and both console.log statements are printed. But the emit()
just doesn't happen.
Any ideas why?
Note: the @node-clicked="nodeClicked($event, citem)"
doesn't seem to make much difference, it just causes the handler to be called twice.
Problem is replicated here on Play.vuejs
After @yuanyxh's answer, I here's an updated Vue SFC Playground link that shows adding a handler on the child node. In this case, children's info are passed up the hierarchy, but not grandchildren.
When you recursively invoke this CustomTreeNode.vue component, you should propagate events down the hierarchy:
// CustomTreeNode.vue
<script setup lang="ts">
// other code here...
const childNodeClicked = (args: [Event, ICustomTreeNode]) => {
emit('node-clicked', [args[0], args[1]])
}
</script>
<template>
// other code here...
<CustomTreeNode
// other code here...
@node-clicked="childNodeClicked($event)"
/>
</template>
Additionally, when you pass parameters as an array:
emit('event-name', ['args1', 'args2'])
The event handler also receives parameters as an array:
const eventHandler = (args: [string, string]) => {};