ctx.Update() 视图切换干扰 ctx.Dispatch 回调执行
现象:从首页(Hero视图)搜索时,ctx.Dispatch 回调不执行,搜索结果不显示;但在结果页再次点击搜索则正常。
问题定位过程:
ctx.Dispatch 被调用但回调没有执行日志ctx.Async 之前调用 ctx.Update() 触发视图切换,会导致后续 ctx.Dispatch 回调被丢弃ctx.Update() 触发大规模 UI 重建(如视图切换)时,会干扰排队的 ctx.Dispatch 回调执行。
错误的代码模式:
func performSearch(ctx app.Context) {
s.HasSearched = true // 这会导致 Render 切换到 Results 视图
ctx.Update() // ❌ 视图切换在此发生
ctx.Async(func() {
// ... HTTP 请求 ...
ctx.Dispatch(func(ctx app.Context) {
// ❌ 这个回调可能不会执行!
s.Results = results
ctx.Update()
})
})
}
修复方案:将状态变更和视图切换移到 ctx.Dispatch 回调内部:
func performSearch(ctx app.Context) {
// ✅ 不要在这里设置 HasSearched 或调用 ctx.Update()
s.IsSearching = true // 仅设置搜索状态,不触发视图切换
ctx.Async(func() {
// ... HTTP 请求 ...
ctx.Dispatch(func(ctx app.Context) {
// ✅ 在回调中设置状态并触发视图切换
s.HasSearched = true // 视图切换在此触发
s.Results = results
ctx.Update()
})
})
}
关键原则:
ctx.Dispatch 回调中的代码是原子执行的,不会被打断ctx.Dispatch 回调中,确保状态变更和 UI 更新同步完成ctx.Async 启动前调用 ctx.Update() 触发视图切换涉及文件: web/app/search.go
history.replaceState() 也会干扰 ctx.Dispatch现象:在 ctx.Dispatch 回调中调用 history.replaceState() 更新 URL,会导致后续 dispatch 回调被丢弃。
修复:使用 setTimeout(..., 0) 延迟执行 URL 更新:
ctx.Dispatch(func(ctx app.Context) {
s.Results = results
ctx.Update()
// ✅ 延迟更新 URL,避免干扰 go-app 事件循环
app.Window().Call("setTimeout", app.FuncOf(func(this app.Value, args []app.Value) interface{} {
s.updateSearchURL()
return nil
}), 0)
})
还没有人回复