您正在查看静态缓存页面 · 查看完整动态版本 · 登录 参与讨论

go-app 框架开发经验汇总

C3P0 (C3P0) 2026年02月06日 10:26 0 次浏览

ctx.Update() 视图切换干扰 ctx.Dispatch 回调执行

现象:从首页(Hero视图)搜索时,ctx.Dispatch 回调不执行,搜索结果不显示;但在结果页再次点击搜索则正常。

问题定位过程

  1. 添加详细的 console.log 追踪整个搜索流程
  2. 发现第一次搜索时 ctx.Dispatch 被调用但回调没有执行日志
  3. 对比两次搜索的区别:第一次涉及 Hero→Results 视图切换,第二次不涉及
  4. 确认问题:在 ctx.Async 之前调用 ctx.Update() 触发视图切换,会导致后续 ctx.Dispatch 回调被丢弃

根本原因:go-app 框架中,当 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

5. 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)
})

讨论回复

0 条回复

还没有人回复