NiceGui树形组件切换按钮数据未更新、事件未触发问题
NiceGui树形组件切换按钮无法触发事件且数据不更新问题排查
问题代码
from nicegui import events, ui def toggleUpdate(e: events.GenericEventArguments) -> None: print(tree._props['nodes']) tree = ui.tree([ {'id': 'numbers', 'description': 'Just some numbers', 'update': True, 'children': [ {'id': '1', 'description': 'The first number', 'update': False}, {'id': '2', 'description': 'The second number', 'update': True}, ]}, {'id': 'letters', 'description': 'Some latin letters', 'update': True, 'children': [ {'id': 'A', 'description': 'The first letter', 'update': True}, {'id': 'B', 'description': 'The second letter', 'update': True}, ]}, ], label_key='id', on_select=lambda e: ui.notify(e.value)) tree.add_slot('default-header', ''' <span :props="props">Node <strong>{{ props.node.id }}</strong></span> ''') tree.add_slot('default-body', r''' <span :props="props">Description: "{{ props.node.description }}" <q-toggle v-model="props.node.update" label="Elemente updaten" left-label @update:model-value="() => $parent.$emit('toggleUpdate', props.node)" /></span> ''') ui.button("Test", on_click=lambda: toggleUpdate("TEST")) tree.on('toggleUpdate', toggleUpdate) tree.on('update:model-value', lambda e: ui.notify(e.args)) ui.run()
当前树形组件可正常显示,但点击切换按钮后数据未发生变更,且toggleUpdate事件未被触发。
错误原因及修正方案
1. 事件触发目标错误
在Vue插槽的q-toggle中使用$parent.$emit无法正确将事件传递到Python端的tree组件。NiceGui的组件事件需要直接通过$emit触发,不需要指定$parent。
2. 数据同步问题
直接修改props.node.update属于单向修改Vue端数据,不会同步回Python端的数据源。需要通过事件将更新后的状态传递回Python,手动更新数据源后刷新组件。
修正后的代码
from nicegui import events, ui # 递归查找树形节点 def find_node(nodes, target_id): for node in nodes: if node['id'] == target_id: return node if 'children' in node: found = find_node(node['children'], target_id) if found: return found return None def toggleUpdate(e: events.GenericEventArguments) -> None: node_id, new_state = e.args # 找到对应节点并更新状态 node = find_node(tree_nodes, node_id) if node: node['update'] = new_state # 刷新树形组件 tree.update() # 打印更新后的数据源 print(tree_nodes) # 把数据源存为变量,方便后续修改 tree_nodes = [ {'id': 'numbers', 'description': 'Just some numbers', 'update': True, 'children': [ {'id': '1', 'description': 'The first number', 'update': False}, {'id': '2', 'description': 'The second number', 'update': True}, ]}, {'id': 'letters', 'description': 'Some latin letters', 'update': True, 'children': [ {'id': 'A', 'description': 'The first letter', 'update': True}, {'id': 'B', 'description': 'The second letter', 'update': True}, ]}, ] tree = ui.tree(tree_nodes, label_key='id', on_select=lambda e: ui.notify(e.value)) tree.add_slot('default-header', ''' <span :props="props">Node <strong>{{ props.node.id }}</strong></span> ''') tree.add_slot('default-body', r''' <span :props="props"> Description: "{{ props.node.description }}" <q-toggle :model-value="props.node.update" label="Elemente updaten" left-label @update:model-value="(new_val) => $emit('toggleUpdate', props.node.id, new_val)" /> </span> ''') ui.button("Test", on_click=lambda: print(tree_nodes)) tree.on('toggleUpdate', toggleUpdate) ui.run()
关键修改点:
- 将数据源提取为
tree_nodes变量,便于Python端修改 - 把
q-toggle的v-model改为:model-value,避免直接修改props,通过@update:model-value触发事件传递节点ID和新状态 - 实现
find_node递归函数查找目标节点,更新后调用tree.update()刷新组件 - 事件触发改为直接
$emit('toggleUpdate', props.node.id, new_val),确保Python端能接收参数
内容的提问来源于stack exchange,提问作者otto.kranz
相关产品推荐
相关产品推荐

