Files
wails3-nuxt4/MIGRATION_GUIDE.md
2026-03-11 18:33:15 +08:00

608 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Wails v3 API 迁移指南alpha.27 → alpha.74
> 本文档基于对 [wailsapp/wails](https://github.com/wailsapp/wails) 仓库 `v3-alpha` 分支最新源码的全面分析。
---
## 总结
**好消息:你当前项目中使用的所有 API 在最新版本中基本保持向后兼容。** 大多数变更是新增功能和选项,而非破坏性更改。唯一需要关注的是 `app.Event.Emit()` 方法可能的签名变化。
---
## 1. `application.New()` 和 `application.Options{}`
### 状态:✅ 向后兼容(新增字段,无破坏性变更)
**你的当前代码:**
```go
app := application.New(application.Options{
Name: "main",
Description: "A demo of using raw HTML & CSS",
Services: []application.Service{...},
Assets: application.AssetOptions{...},
Mac: application.MacOptions{...},
})
```
**变更内容:**
`Options` 结构体新增了大量可选字段,但原有字段完全保留:
| 新增字段 | 类型 | 说明 |
|---------|------|------|
| `Icon` | `[]byte` | 应用图标(用于默认关于框) |
| `Logger` | `*slog.Logger` | 自定义日志记录器 |
| `LogLevel` | `slog.Level` | 日志级别 |
| `MarshalError` | `func(error) []byte` | 自定义服务方法错误序列化 |
| `BindAliases` | `map[uint32]uint32` | 绑定方法别名 ID |
| `Flags` | `map[string]any` | 传递给前端的键值对 |
| `PanicHandler` | `func(*PanicDetails)` | panic 处理器 |
| `KeyBindings` | `map[string]func(window Window)` | 全局键绑定 |
| `OnShutdown` | `func()` | 关闭前回调(阻塞) |
| `PostShutdown` | `func()` | 关闭后回调 |
| `ShouldQuit` | `func() bool` | 控制是否允许退出 |
| `RawMessageHandler` | `func(window Window, message string, originInfo *OriginInfo)` | 自定义前端消息处理 |
| `WarningHandler` | `func(string)` | 警告处理器 |
| `ErrorHandler` | `func(err error)` | 错误处理器 |
| `FileAssociations` | `[]string` | 文件关联(如 `[".txt", ".md"]` |
| `SingleInstance` | `*SingleInstanceOptions` | 单实例模式配置 |
| `Transport` | `Transport` | 自定义 IPC 传输层 |
| `Server` | `ServerOptions` | HTTP 服务器模式配置 |
| `DisableDefaultSignalHandler` | `bool` | 禁用默认信号处理 |
| `IOS` | `IOSOptions` | iOS 平台配置 |
| `Android` | `AndroidOptions` | Android 平台配置 |
新增 `WindowsOptions` 字段:
```go
Windows: application.WindowsOptions{
WndClass: "MyApp",
DisableQuitOnLastWindowClosed: true,
WebviewUserDataPath: "",
WebviewBrowserPath: "",
EnabledFeatures: []string{},
DisabledFeatures: []string{},
AdditionalBrowserArgs: []string{},
WndProcInterceptor: nil,
},
```
新增 `LinuxOptions` 字段:
```go
Linux: application.LinuxOptions{
DisableQuitOnLastWindowClosed: true,
ProgramName: "my-app",
},
```
**迁移建议:** 无需修改。可根据需要使用新增字段。
---
## 2. `application.Service` 和 `application.NewService()` 注册 API
### 状态:✅ 向后兼容(新增 `NewServiceWithOptions`
**你的当前代码:**
```go
Services: []application.Service{
application.NewService(appService),
application.NewService(&GreetService{}),
},
```
**变更内容:**
- `NewService[T any](instance *T) Service`**签名不变**
- 新增 `NewServiceWithOptions[T any](instance *T, options ServiceOptions) Service`
`ServiceOptions` 结构体:
```go
type ServiceOptions struct {
Name string // 服务名称
Route string // HTTP 路由前缀,挂载 http.Handler
MarshalError func(error) []byte // 单服务的错误序列化
}
```
新增 `DefaultServiceOptions` 变量。
**新增可选接口:**
```go
// 可选:自定义服务名称
type ServiceName interface {
ServiceName() string
}
```
**示例:使用新 API**
```go
// 旧方式(仍然有效)
application.NewService(appService)
// 新方式:带选项
application.NewServiceWithOptions(appService, application.ServiceOptions{
Name: "app-service",
Route: "/api/app",
})
```
**迁移建议:** 无需修改。如需自定义服务路由或名称,可使用 `NewServiceWithOptions`
---
## 3. `ServiceStartup` 方法签名
### 状态:✅ 完全相同,无变更
**你的当前代码:**
```go
func (a *App) ServiceStartup(ctx context.Context, options application.ServiceOptions) error {
a.ctx = ctx
return nil
}
```
**分析:** 签名完全一致:`ServiceStartup(ctx context.Context, options ServiceOptions) error`
**新增可选生命周期接口:**
```go
// 可选:服务关闭时调用
type ServiceShutdown interface {
ServiceShutdown() error
}
```
**示例:添加关闭钩子**
```go
func (a *App) ServiceShutdown() error {
log.Println("App service shutting down")
return nil
}
```
**迁移建议:** 无需修改。可选择实现 `ServiceShutdown()` 接口。
---
## 4. `app.Window.NewWithOptions()` / `WebviewWindowOptions`
### 状态:✅ 向后兼容(大量新增选项)
**你的当前代码:**
```go
mainWindow := app.Window.NewWithOptions(application.WebviewWindowOptions{
Title: "Window 1",
Mac: application.MacWindow{
InvisibleTitleBarHeight: 50,
Backdrop: application.MacBackdropTranslucent,
TitleBar: application.MacTitleBarHiddenInset,
},
BackgroundColour: application.NewRGB(27, 38, 54),
URL: "/",
Width: 1240,
Height: 850,
})
```
**变更内容:**
`app.Window` 类型为 `*WindowManager`之前已是类似的管理器模式API 不变:
- `Window.New() *WebviewWindow`
- `Window.NewWithOptions(WebviewWindowOptions) *WebviewWindow`
- 新增 `Window.GetByName(name string) (Window, bool)`
- 新增 `Window.GetByID(id uint) (Window, bool)`
- 新增 `Window.Current() Window`
- 新增 `Window.GetAll() []Window`
- 新增 `Window.OnCreate(callback func(Window))` — 窗口创建回调
`WebviewWindowOptions` 新增字段:
| 新增字段 | 类型 | 说明 |
|---------|------|------|
| `KeyBindings` | `map[string]func(window Window)` | 窗口级键绑定 |
| `IgnoreMouseEvents` | `bool` | 忽略鼠标事件Windows + Mac |
| `ContentProtectionEnabled` | `bool` | 内容保护(防截屏) |
| `HideOnFocusLost` | `bool` | 失去焦点时隐藏 |
| `HideOnEscape` | `bool` | 按 Esc 键隐藏 |
| `UseApplicationMenu` | `bool` | 使用应用全局菜单 |
| `DefaultContextMenuDisabled` | `bool` | 禁用默认右键菜单 |
| `DevToolsEnabled` | `bool` | 启用开发者工具 |
`MacWindow` 新增字段:
| 新增字段 | 类型 | 说明 |
|---------|------|------|
| `EventMapping` | `map[events.WindowEventType]events.WindowEventType` | 事件映射 |
| `EnableFraudulentWebsiteWarnings` | `bool` | 欺诈网站警告 |
| `WebviewPreferences` | `MacWebviewPreferences` | WebView 偏好设置 |
| `WindowLevel` | `MacWindowLevel` | 窗口层级 |
| `CollectionBehavior` | `MacWindowCollectionBehavior` | Spaces 和全屏行为 |
| `LiquidGlass` | `MacLiquidGlass` | Liquid Glass 效果macOS 15.0+ |
`WindowsWindow` 新增字段:
- `HiddenOnTaskbar` — 从任务栏隐藏
- `EnableSwipeGestures` — 触控滑动手势
- `Menu *Menu` — 窗口菜单
- `Permissions` — WebView2 权限控制
- `ExStyle` — 扩展窗口样式
- `GeneralAutofillEnabled` / `PasswordAutosaveEnabled`
- `WindowDidMoveDebounceMS` / `ResizeDebounceMS`
新增 `LinuxWindow` 结构体:
```go
Linux: application.LinuxWindow{
Icon: []byte{},
WindowIsTranslucent: false,
WebviewGpuPolicy: application.WebviewGpuPolicyOnDemand,
Menu: myMenu,
MenuStyle: application.LinuxMenuStylePrimaryMenu,
},
```
**迁移建议:** 无需修改。可利用 `HideOnFocusLost``HideOnEscape` 简化你的系统托盘窗口逻辑。
---
## 5. `events.Common.WindowClosing` 和 `RegisterHook`
### 状态:✅ 完全相同,无变更
**你的当前代码:**
```go
mainWindow.RegisterHook(events.Common.WindowClosing, func(event *application.WindowEvent) {
mainWindow.Hide()
event.Cancel()
})
```
**分析:**
- `events.Common.WindowClosing` — 仍然存在(值 `1028`
- `RegisterHook` 签名不变:`RegisterHook(eventType events.WindowEventType, callback func(event *WindowEvent)) func()`
- `WindowEvent.Cancel()` 方法不变
- 现在 `RegisterHook` 返回一个 `func()` 取消函数alpha.27 可能也是如此)
**补充:`OnWindowEvent` 方法**
```go
// OnWindowEvent 用于注册窗口事件监听器(非 Hook
mainWindow.OnWindowEvent(events.Common.WindowClosing, func(event *application.WindowEvent) {
// Hook 可以取消事件OnWindowEvent 不能
})
```
**迁移建议:** 无需修改。
---
## 6. `app.SystemTray.New()` 系统托盘 API
### 状态:✅ 向后兼容(大量功能增强)
**你的当前代码:**
```go
systray := app.SystemTray.New()
systray.SetMenu(trayMenu)
systray.OnClick(func() {
mainWindow.Show()
mainWindow.Focus()
})
```
**变更内容:**
原有 API 完全保留,新增以下方法:
| 新增方法 | 说明 |
|---------|------|
| `OnRightClick(func())` | 右键点击处理 |
| `OnDoubleClick(func())` | 双击处理 |
| `OnRightDoubleClick(func())` | 右键双击处理 |
| `OnMouseEnter(func())` | 鼠标进入处理 |
| `OnMouseLeave(func())` | 鼠标离开处理 |
| `AttachWindow(window Window)` | 绑定窗口到托盘(自动切换显示/隐藏) |
| `WindowOffset(offset int)` | 设置窗口与托盘的间距 |
| `WindowDebounce(debounce time.Duration)` | Windows 上防抖设置 |
| `Show()` / `Hide()` | 显示/隐藏托盘图标 |
| `OpenMenu()` | 打开托盘菜单 |
| `ShowWindow()` / `HideWindow()` / `ToggleWindow()` | 窗口操作 |
| `SetDarkModeIcon(icon []byte)` | 深色模式图标 |
| `SetTemplateIcon(icon []byte)` | macOS 模板图标 |
| `SetTooltip(tooltip string)` | 设置提示文本 |
| `SetLabel(label string)` | 设置标签文本 |
| `SetIconPosition(IconPosition)` | 设置图标位置 |
| `Destroy()` | 销毁托盘 |
**推荐:使用 `AttachWindow` 简化代码**
你当前手动实现的"点击托盘显示/隐藏窗口"逻辑,现在可以用内置的 `AttachWindow` 替代:
```go
// 新方式(推荐)
systray := app.SystemTray.New()
systray.SetMenu(trayMenu)
systray.AttachWindow(mainWindow).WindowOffset(10)
// AttachWindow 自动处理点击切换显示/隐藏
```
**迁移建议:** 无需修改。推荐使用 `AttachWindow` 简化托盘-窗口绑定逻辑。
---
## 7. `app.Event.Emit()` 事件 API
### 状态:⚠️ 需要验证(可能有方法名变更)
**你的当前代码:**
```go
app.Event.Emit("time", now)
```
**分析:**
`app.Event` 类型为 `*EventManager`。在最新源码中:
- `WebviewWindow.EmitEvent(name string, data ...any) bool` — 窗口级事件发射
- 内部调用 `globalApplication.Event.EmitEvent(event *CustomEvent)`
`EventManager` 上的方法可能从 `Emit(name, data...)` 更名为 `EmitEvent`,或两者共存。
**可能的迁移方式:**
```go
// 如果 Emit 仍然存在(最可能的情况)
app.Event.Emit("time", now)
// 如果需要使用 EmitEvent
app.EmitEvent(&application.CustomEvent{
Name: "time",
Data: now,
})
```
**新增事件 API 特性:**
- 严格事件模式:构建标签 `strictevents` 启用事件注册检查
- `OnApplicationEvent` — 监听应用级事件
- 事件发射现在返回 `bool`,指示事件是否被 Hook 取消
**迁移建议:** 升级后编译测试。如果 `Emit` 编译失败,尝试改用 `EmitEvent` 或查看最新文档。
---
## 8. `application.AssetOptions` 和 `AssetFileServerFS`
### 状态:✅ 完全兼容(新增 `BundledAssetFileServer`
**你的当前代码:**
```go
Assets: application.AssetOptions{
Handler: application.AssetFileServerFS(assets),
},
```
**变更内容:**
`AssetOptions` 结构体字段不变:
```go
type AssetOptions struct {
Handler http.Handler // 不变
Middleware Middleware // 不变
DisableLogging bool // 不变
}
```
`AssetFileServerFS` 函数签名不变:
```go
func AssetFileServerFS(assets fs.FS) http.Handler
```
**新增:`BundledAssetFileServer`**
```go
func BundledAssetFileServer(assets fs.FS) http.Handler
```
`AssetFileServerFS` 的区别:`BundledAssetFileServer` 额外在 `/wails/runtime.js` 路径提供编译后的运行时 JS 文件。
**新增:中间件链**
```go
Assets: application.AssetOptions{
Handler: application.AssetFileServerFS(assets),
Middleware: application.ChainMiddleware(
myAuthMiddleware,
myLoggingMiddleware,
),
DisableLogging: true,
},
```
**迁移建议:** 无需修改。如果需要运行时 JS 内置服务,可考虑切换到 `BundledAssetFileServer`
---
## 9. `MacOptions`, `MacWindow`, `MacTitleBarHiddenInset`, `MacBackdropTranslucent`
### 状态:✅ 完全兼容(新增选项)
**你的当前代码:**
```go
Mac: application.MacOptions{
ApplicationShouldTerminateAfterLastWindowClosed: true,
},
// ...
Mac: application.MacWindow{
InvisibleTitleBarHeight: 50,
Backdrop: application.MacBackdropTranslucent,
TitleBar: application.MacTitleBarHiddenInset,
},
```
**分析:**
所有使用的类型和常量均未更改:
- `MacOptions.ApplicationShouldTerminateAfterLastWindowClosed` — ✅ 存在
- `MacOptions.ActivationPolicy` — ✅ 存在
- `MacWindow.InvisibleTitleBarHeight` — ✅ 存在
- `MacWindow.Backdrop` (类型 `MacBackdrop`) — ✅ 存在
- `MacWindow.TitleBar` (类型 `MacTitleBar`) — ✅ 存在
- `MacBackdropTranslucent` 常量 — ✅ 存在
- `MacTitleBarHiddenInset` 预定义变量 — ✅ 存在
**新增 `MacBackdrop` 值:**
```go
const (
MacBackdropNormal MacBackdrop = iota // 不变
MacBackdropTransparent // 不变
MacBackdropTranslucent // 不变
MacBackdropLiquidGlass // 新增macOS 15.0+ Liquid Glass
)
```
**新增 `MacTitleBar` 预定义变量:**
```go
var MacTitleBarHiddenInsetUnified = MacTitleBar{...} // 新增
```
**新增 `MacWindow` 功能:**
- `MacWindowLevel` — 控制窗口层级(`normal`, `floating`, `modalPanel` 等)
- `MacWindowCollectionBehavior` — 控制 Spaces 和全屏行为
- `MacLiquidGlass` — Liquid Glass 效果配置
- `MacWebviewPreferences` — WebView 偏好设置
**Liquid Glass 示例macOS 15.0+**
```go
Mac: application.MacWindow{
Backdrop: application.MacBackdropLiquidGlass,
LiquidGlass: application.MacLiquidGlass{
Style: application.LiquidGlassStyleAutomatic,
CornerRadius: 12,
TintColor: &application.RGBA{Red: 255, Green: 255, Blue: 255, Alpha: 128},
},
},
```
**迁移建议:** 无需修改。
---
## 10. `application.Context` 类型(菜单点击处理器)
### 状态:✅ 完全相同,无变更
**你的当前代码:**
```go
trayMenu.Add("显示主窗口").OnClick(func(ctx *application.Context) {
mainWindow.Show()
mainWindow.Focus()
})
```
**分析:**
- `Context` 结构体不变
- `MenuItem.OnClick(func(*Context)) *MenuItem` — 签名不变
- `Context.ClickedMenuItem() *MenuItem` — 不变
- `Context.IsChecked() bool` — 不变
- `Context.ContextMenuData() string` — 不变
`Menu.Add(label string) *MenuItem` — 不变
**迁移建议:** 无需修改。
---
## 其他重要新增功能
### 窗口接口 `Window`
最新版本定义了 `Window` 接口,`*WebviewWindow` 实现该接口。这允许更灵活的窗口操作。
### 新增 Manager 模式
所有子系统现在通过 Manager 模式访问:
```go
app.Window // *WindowManager
app.SystemTray // *SystemTrayManager
app.Event // *EventManager
app.Menu // *MenuManager
app.Dialog // *DialogManager
app.Screen // *ScreenManager
app.Clipboard // *ClipboardManager
app.Browser // *BrowserManager
app.Env // *EnvironmentManager
app.KeyBinding // *KeyBindingManager
app.ContextMenu // *ContextMenuManager
```
### 运行时服务注册
```go
app.RegisterService(application.NewService(myService))
```
### HTTP Transport
```go
Transport: application.NewHTTPTransport(),
```
### Server 模式
使用 `server` 构建标签,应用可作为 HTTP 服务器运行:
```go
Server: application.ServerOptions{
Host: "0.0.0.0",
Port: 8080,
},
```
### 新增平台支持
- **iOS** — `IOSOptions` 包含 WebView 偏好、原生标签栏等
- **Android** — `AndroidOptions` 包含 WebView 配置
---
## 迁移步骤
1. **更新依赖版本:**
```bash
go get github.com/wailsapp/wails/v3@v3.0.0-alpha.74
go mod tidy
```
2. **编译测试:**
```bash
go build .
```
3. **检查 `app.Event.Emit()` 是否编译通过。** 如果失败,尝试:
- 使用 `app.EmitEvent(name, data...)` 或
- 查看 `EventManager` 的最新方法列表
4. **可选优化:**
- 使用 `systray.AttachWindow(mainWindow)` 替代手动托盘-窗口切换逻辑
- 考虑使用 `BundledAssetFileServer` 替代 `AssetFileServerFS`
- 利用 `WebviewWindowOptions.HideOnEscape` 和 `HideOnFocusLost` 简化窗口行为
- 实现 `ServiceShutdown()` 接口处理优雅关闭
5. **更新前端绑定:**
```bash
# 如果使用 Wails CLI 生成绑定
wails3 generate bindings
```
---
## 你的项目兼容性矩阵
| API 使用点 | 当前代码 | 兼容性 | 操作 |
|-----------|---------|--------|------|
| `application.New(Options{})` | ✅ | 兼容 | 无需修改 |
| `application.NewService()` | ✅ | 兼容 | 无需修改 |
| `ServiceStartup(ctx, opts)` | ✅ | 兼容 | 无需修改 |
| `app.Window.NewWithOptions()` | ✅ | 兼容 | 无需修改 |
| `events.Common.WindowClosing` | ✅ | 兼容 | 无需修改 |
| `RegisterHook()` | ✅ | 兼容 | 无需修改 |
| `app.SystemTray.New()` | ✅ | 兼容 | 无需修改 |
| `app.Event.Emit()` | ⚠️ | 需验证 | 编译测试 |
| `AssetFileServerFS()` | ✅ | 兼容 | 无需修改 |
| `MacBackdropTranslucent` | ✅ | 兼容 | 无需修改 |
| `MacTitleBarHiddenInset` | ✅ | 兼容 | 无需修改 |
| `MacOptions{}` | ✅ | 兼容 | 无需修改 |
| `*application.Context` | ✅ | 兼容 | 无需修改 |
| `app.NewMenu()` | ✅ | 兼容 | 无需修改 |
| `app.Quit()` | ✅ | 兼容 | 无需修改 |