#1107·go-app

当函数为闭包时,OnChange 无法更新事件处理程序

作者: flyn-org创建于 2026年1月28日更新于 2026年2月5日

我有以下代码,它导致 go-app 以我所预期的方式运行: app.Range(c.expenses).Slice(func(i int) app.UI { return app.Tr(). Body( app.Td(). Class("text-end"). Body( app.Input(). ID(fmt.Sprintf("expense-%d-selected", i)). Type("checkbox"). OnChange(func(ctx app.Context, e app.Event) { c.expenses[i].selected = ctx.JSSrc().Get("checked").Bool() }), ... }), app.Range(c.jobs).Slice(func(i int) app.UI { return app.Tr(). Body( app.Td(). Class("text-end"). Body( app.Input(). ID(fmt.Sprintf("job-%d-selected", i)). Type("checkbox"). OnChange(func(ctx app.Context, e app.Event) { c.jobs[i].selected = ctx.JSSrc().Get("checked").Bool() }), ... }),

看起来,此代码在某些情况下不会更新 HTMLTd 的“change”处理程序,而这种情况需要更新。例如,假设通过此代码执行了两次操作:(1) c.jobs 中有一个项,c.expenses 中有两个项,(2) c.jobs 中有两个项,c.expenses 中有一个。在两种情况下,这将生成三个 `tr` 元素,其中最后一个在两次操作中仅在其“change”处理程序上有所不同。(某些其他 UI 元素的更改会导致两次操作使用这些值。) 在此情况下,第二次操作将保留第三个“change”处理程序未修改,因此在处理程序的上下文中 `i = 1`。但是,这将导致对 `c.expenses` 的越界访问,即使在操作中 `i = 1`,但 `c.expenses` 中只有一个项。

内容来源: maxence-charriere/go-app