mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-06 01:21:25 +08:00
403 lines
14 KiB
Markdown
403 lines
14 KiB
Markdown
# v3的更改
|
||
|
||
!!! note这是当前的无序更改脑升级。很快它将组织成一个更易读的格式。
|
||
|
||
## 选项
|
||
|
||
自v2以来,应用程序选项已经进行了修订。
|
||
|
||
## 事件
|
||
|
||
在v3中,有3种类型的事件:
|
||
|
||
- 应用程序事件
|
||
- 窗口事件
|
||
- 自定义事件
|
||
|
||
### 应用程序事件
|
||
|
||
应用程序事件是由应用程序发出的事件。这些事件包括macOS上
|
||
的`ApplicationDidFinishLaunching`等本机事件。
|
||
|
||
### 窗口事件
|
||
|
||
窗口事件是由窗口发出的事件。这些事件包括macOS上的`WindowDidBecomeMain`等本机事
|
||
件。还定义了常见事件,以便它们在跨平台上工作,例如`WindowClosing`。
|
||
|
||
### 自定义事件
|
||
|
||
用户定义的事件称为`WailsEvents`。这是为了将它们与用于与浏览器通信的`Event`对象区
|
||
分开来。WailsEvents现在是封装事件的对象。这包括事件名称,数据和事件的源。
|
||
|
||
与WailsEvent关联的数据现在是单个值。如果需要多个值,则可以使用struct。
|
||
|
||
### 事件回调和`Emit`函数签名
|
||
|
||
事件回调的签名(由`On`,`Once`和`OnMultiple`使用)已更改。在v2中,回调函数接收可
|
||
选数据。在v3中,回调函数接收包含与事件相关的所有数据的`WailsEvent`对象。
|
||
|
||
类似地,`Emit`函数已更改。它现在不再接受名称和可选数据,而是接受一
|
||
个`WailsEvent`对象,它将发出该对象。
|
||
|
||
### `Off`和`OffAll`
|
||
|
||
在v2中,`Off`和`OffAll`调用将删除JS和Go中的事件。由于v3具有多窗口的特性,因此已
|
||
更改为这些方法仅适用于调用它们的上下文。例如,如果你在一个窗口中调用`Off`,它仅
|
||
会删除该窗口的事件。如果你在Go中使用`Off`,它只会删除Go的事件。
|
||
|
||
### Hooks
|
||
|
||
事件钩子是v3中的新功能。它们允许您钩入事件系统,并在发出某些事件时执行操作。例
|
||
如,您可以钩入`WindowClosing`事件,在窗口关闭之前执行一些清理操作。钩子可以在应
|
||
用程序级别或窗口级别使用`RegisterHook`进行注册。应用程序级别适用于应用程序事件。
|
||
仅当窗口级别钩子与其注册的窗口一起调用。
|
||
|
||
### 日志记录
|
||
|
||
在v2中,日志记录会混淆,因为应用程序日志和系统(内部)日志都使用相同的记录器。我
|
||
们已经对此进行了简化:
|
||
|
||
- 内部日志现在使用标准的Go `slog`记录器处理。这是通过应用程序选项中的`logger`选
|
||
项进行配置的。默认情况下,这使用[tint](https://github.com/lmittmann/tint)记录
|
||
器。
|
||
- 现在可以通过新的`log`插件进行应用程序日志记录,它在底层使用`slog`。此插件提供
|
||
了一个简单的用于记录到控制台的API。它在Go和JS中都可用。
|
||
|
||
### 开发人员注意事项
|
||
|
||
在Go中发出事件时,它会将事件分派到本地的Go侦听器以及应用程序中的每个窗口。在JS中
|
||
发出事件时,它现在会将事件发送到应用程序。这将被处理,就好像它是在Go中发出的,但
|
||
是发送者ID将是窗口的ID。
|
||
|
||
## 窗口
|
||
|
||
Window API在很大程度上保持不变,但方法现在是在窗口实例而不是运行时上。一些值得注
|
||
意的变化是:
|
||
|
||
- 窗口现在具有标识它们的名称。用于在发出事件时标识窗口。
|
||
- 窗口上现在有更多以前不可用的方法,例如`AbsolutePosition`和`ToggleDevTools`。
|
||
- 窗口现在可以通过本机拖放接受文件。有关详细信息,请参阅拖放部分。
|
||
|
||
## 剪切板
|
||
|
||
剪贴板API已经简化。现在有一个单独的`Clipboard`对象,可以用于读取和写入剪贴
|
||
板。`Clipboard`对象在Go和JS中都可用。`SetText()`用于设置文本,`Text()`用于获取文
|
||
本。
|
||
|
||
## 绑定
|
||
|
||
绑定的工作方式与v2类似,通过提供一种将结构方法绑定到前端的方式。这些可以在前端使
|
||
用由`wails3 generate bindings`命令生成的绑定包装器来调用:
|
||
|
||
```javascript
|
||
// @ts-check
|
||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||
// This file is automatically generated. DO NOT EDIT
|
||
|
||
import { main } from "./models";
|
||
|
||
window.go = window.go || {};
|
||
window.go.main = {
|
||
GreetService: {
|
||
/**
|
||
* GreetService.Greet
|
||
* Greet greets a person
|
||
* @param name {string}
|
||
* @returns {Promise<string>}
|
||
**/
|
||
Greet: function (name) {
|
||
wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0));
|
||
},
|
||
|
||
/**
|
||
* GreetService.GreetPerson
|
||
* GreetPerson greets a person
|
||
* @param person {main.Person}
|
||
* @returns {Promise<string>}
|
||
**/
|
||
GreetPerson: function (person) {
|
||
wails.CallByID(4021313248, ...Array.prototype.slice.call(arguments, 0));
|
||
},
|
||
},
|
||
};
|
||
```
|
||
|
||
默认情况下,绑定的方法是混淆的,并使用uint32 ID进行标识,该ID是使
|
||
用[FNV哈希算法](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function)计
|
||
算的。这是为了防止方法名称在生产构建中被暴露出来。在调试模式下,方法ID与计算的方
|
||
法ID一起记录,以帮助调试。如果您希望增加额外的混淆层,可以使用`BindAliases`选
|
||
项。这允许您指定别名ID与方法ID的映射。当前端使用ID调用方法时,方法ID将首先在别名
|
||
映射中查找匹配项。如果找不到,它将假定是标准方法ID,并尝试以通常的方式查找方法。
|
||
|
||
示例:
|
||
|
||
```go
|
||
app := application.New(application.Options{
|
||
Bind: []any{
|
||
&GreetService{},
|
||
},
|
||
BindAliases: map[uint32]uint32{
|
||
1: 1411160069,
|
||
2: 4021313248,
|
||
},
|
||
Assets: application.AssetOptions{
|
||
FS: assets,
|
||
},
|
||
Mac: application.MacOptions{
|
||
ApplicationShouldTerminateAfterLastWindowClosed: true,
|
||
},
|
||
})
|
||
```
|
||
|
||
现在我们可以使用此别名在前端调用:`wails.Call(1, "world!")`。
|
||
|
||
### 不安全调用
|
||
|
||
如果您不介意在二进制文件中以明文形式提供调用,并且不打算使
|
||
用[garble](https://github.com/burrowers/garble),那么可以使用不安全
|
||
的`wails.CallByName()`方法。此方法接受要调用的方法的完全限定名称和要传递给它的参
|
||
数。示例:
|
||
|
||
```go
|
||
wails.CallByName("main.GreetService.Greet", "world!")
|
||
```
|
||
|
||
!!! danger
|
||
|
||
这仅作为开发的便利方法提供。不建议在生产中使用此方法。
|
||
|
||
## 对话框
|
||
|
||
对话框现在在JavaScript中可用!
|
||
|
||
### Windows
|
||
|
||
Windows中的对话框按钮是不可配置的,根据对话框的类型是恒定的。要在按下按钮时触发
|
||
回调,请创建一个具有与您希望附加回调的按钮相同名称的按钮。示例:创建一个标签为“
|
||
确定”的按钮,并使用`OnClick()`方法设置回调方法:
|
||
|
||
```go
|
||
dialog := app.QuestionDialog().
|
||
SetTitle("Update").
|
||
SetMessage("The cancel button is selected when pressing escape")
|
||
ok := dialog.AddButton("Ok")
|
||
ok.OnClick(func() {
|
||
// Do something
|
||
})
|
||
no := dialog.AddButton("Cancel")
|
||
dialog.SetDefaultButton(ok)
|
||
dialog.SetCancelButton(no)
|
||
dialog.Show()
|
||
```
|
||
|
||
## 拖放
|
||
|
||
可以按窗口启用本机拖放。只需将`EnableDragAndDrop`窗口配置选项设置为`true`,窗口
|
||
将允许将文件拖放到其上。当这种情况发生时,将发出`events.FilesDropped`事件。然后
|
||
可以使用`WindowEvent.Context()`中的`DroppedFiles()`方法检索文件名。这将返回一个
|
||
包含文件名的字符串切片。
|
||
|
||
## 上下文菜单
|
||
|
||
上下文菜单是当用户右键单击元素时显示的上下文菜单。创建上下文菜单与创建标准菜单相
|
||
同,使用`app.NewMenu()`。要使上下文菜单对窗口可用,请调
|
||
用`window.RegisterContextMenu(name, menu)`。名称将是上下文菜单的ID,并由前端使
|
||
用。
|
||
|
||
要指示元素具有上下文菜单,请将`data-contextmenu`属性添加到元素。此属性的值应为先
|
||
前在窗口中注册的上下文菜单的名称。
|
||
|
||
可以在应用程序级别注册上下文菜单,使其对所有窗口可用。可以使
|
||
用`app.RegisterContextMenu(name, menu)`完成此操作。如果在窗口级别找不到上下文菜
|
||
单,则将检查应用程序上下文菜单。`v3/examples/contextmenus`中可以找到此演示。
|
||
|
||
## Wails标记语言(WML)
|
||
|
||
Wails标记语言是一种简单的标记语言,允许您在没有JavaScript的情况下向标准HTML元素
|
||
添加功能。
|
||
|
||
当前支持以下标签:
|
||
|
||
### `data-wml-event`
|
||
|
||
这指定单击元素时将发出Wails事件。属性的值应为要发出的事件的名称。
|
||
|
||
示例:
|
||
|
||
```html
|
||
<button data-wml-event="myevent">Click Me</button>
|
||
```
|
||
|
||
有时您需要用户确认操作。可以通过向元素添加`data-wml-confirm`属性来完成。此属性的
|
||
值将是要显示给用户的消息。
|
||
|
||
示例:
|
||
|
||
```html
|
||
<button data-wml-event="delete-all-items" data-wml-confirm="Are you sure?">
|
||
Delete All Items
|
||
</button>
|
||
```
|
||
|
||
### `data-wml-window`
|
||
|
||
可以通过将`data-wml-window`属性添加到元素中来调用任何`wails.window`方法。属性的
|
||
值应为要调用的方法的名称。方法名称应与导出的方法的名称完全匹配。
|
||
|
||
```html
|
||
<button data-wml-window="Close">Close Window</button>
|
||
```
|
||
|
||
### `data-wml-trigger`
|
||
|
||
此属性指定应触发操作的javascript事件。默认为`click`。
|
||
|
||
```html
|
||
<button data-wml-event="hover-box" data-wml-trigger="mouseover">
|
||
Hover over me!
|
||
</button>
|
||
```
|
||
|
||
## 系统托盘
|
||
|
||
Wails 3附带了一个内置的系统托盘。这是一个完全功能的系统托盘,旨在尽可能简单地使
|
||
用。可以设置托盘的图标、工具提示和菜单。还可以“附加”窗口到系统托盘。这样做将提供
|
||
以下功能:
|
||
|
||
- 单击托盘图标会切换窗口可见性
|
||
- 右键单击托盘将打开菜单(如果有)
|
||
|
||
在macOS上,如果没有附加的窗口,则托盘将使用显示菜单的默认方法(任何按钮)。如果
|
||
有附加的窗口但没有菜单,则托盘将切换窗口,而不管按下的按钮如何。
|
||
|
||
## 插件
|
||
|
||
插件是扩展Wails应用程序功能的一种方式。
|
||
|
||
### 创建插件
|
||
|
||
插件是符合以下接口的标准Go结构:
|
||
|
||
```go
|
||
type Plugin interface {
|
||
Name() string
|
||
Init(*application.App) error
|
||
Shutdown()
|
||
CallableByJS() []string
|
||
InjectJS() string
|
||
}
|
||
```
|
||
|
||
`Name()`方法返回插件的名称。这用于记录目的。
|
||
|
||
`Init(*application.App) error`方法在加载插件时调用。`*application.App`参数是加载
|
||
插件的应用程序。任何错误都将阻止应用程序启动。
|
||
|
||
`Shutdown()`方法在应用程序关闭时调用。
|
||
|
||
`CallableByJS()`方法返回可以从前端调用的导出函数列表。这些方法名称必须与插件导出
|
||
的方法名称完全匹配。
|
||
|
||
`InjectJS()`方法返回应注入到创建的所有窗口中的JavaScript。这对于添加与插件补充的
|
||
自定义JavaScript函数很有用。
|
||
|
||
### 提示
|
||
|
||
#### 枚举
|
||
|
||
在Go中,枚举通常被定义为类型和一组常量。例如:
|
||
|
||
```go
|
||
type MyEnum int
|
||
|
||
const (
|
||
MyEnumOne MyEnum = iota
|
||
MyEnumTwo
|
||
MyEnumThree
|
||
)
|
||
```
|
||
|
||
由于Go和JavaScript之间的不兼容性,无法以这种方式使用自定义类型。最好的策略是为
|
||
float64使用类型别名:
|
||
|
||
```go
|
||
type MyEnum = float64
|
||
|
||
const (
|
||
MyEnumOne MyEnum = iota
|
||
MyEnumTwo
|
||
MyEnumThree
|
||
)
|
||
```
|
||
|
||
在Javascript中,您可以使用以下代码:
|
||
|
||
```js
|
||
const MyEnum = {
|
||
MyEnumOne: 0,
|
||
MyEnumTwo: 1,
|
||
MyEnumThree: 2,
|
||
};
|
||
```
|
||
|
||
- 为什么使用`float64`?不能使用`int`吗?
|
||
- 因为JavaScript没有“int”的概念。一切都是`number`,在Go中会转换为`float64`。Go
|
||
的反射包中还有类型转换的限制,这意味着使用`int`是行不通的。
|
||
|
||
### BackgroundColour
|
||
|
||
在v2中,这是指向`RGBA`结构的指针。在v3中,这是`RGBA`结构的值。
|
||
|
||
### WindowIsTranslucent
|
||
|
||
已删除此标志。现在有一个`BackgroundType`标志,可用于设置窗口应具有的背景类型。此
|
||
标志可以设置为以下任何值:
|
||
|
||
- `BackgroundTypeSolid` - 窗口将具有实心背景
|
||
- `BackgroundTypeTransparent` - 窗口将具有透明背景
|
||
- `BackgroundTypeTranslucent` - 窗口将具有半透明背景
|
||
|
||
在Windows上,如果`BackgroundType`设置为`BackgroundTypeTranslucent`,则可以使
|
||
用`WindowsWindow`选项中的`BackdropType`标志设置透明度的类型。这可以设置为以下任
|
||
何值:
|
||
|
||
- `Auto` - 窗口将使用系统确定的效果
|
||
- `None` - 窗口没有背景
|
||
- `Mica` - 窗口使用Mica效果
|
||
- `Acrylic` - 窗口使用丙烯酸效果
|
||
- `Tabbed` - 窗口使用选项卡效果
|
||
|
||
## Windows Application Options
|
||
|
||
### WndProcInterceptor
|
||
|
||
如果设置了此标志,将拦截WndProc并调用该函数。这允许您直接处理Windows消息。该函数
|
||
应具有以下签名:
|
||
|
||
```go
|
||
func(hwnd uintptr, msg uint32, wParam, lParam uintptr) (returnValue uintptr, shouldReturn)
|
||
```
|
||
|
||
如果`shouldReturn`值设置为`true`,则`returnValue`将由主wndProc方法返回。如果设置
|
||
为`false`,将忽略返回值,并且消息将继续由主wndProc方法处理。
|
||
|
||
## 在关闭时隐藏窗口+OnBeforeClose
|
||
|
||
在v2中,有一个`HideWindowOnClose`标志,用于在关闭窗口时隐藏窗
|
||
口。`HideWindowOnClose`标志与`OnBeforeClose`回调之间存在逻辑重叠。在v3中,已删
|
||
除`HideWindowOnClose`标志,并将`OnBeforeClose`回调重命名为`ShouldClose`。当用户
|
||
尝试关闭窗口时,将调用`ShouldClose`回调。如果回调返回`true`,窗口将关闭。如果返
|
||
回`false`,窗口将不会关闭。这可以用于隐藏窗口而不是关闭窗口。
|
||
|
||
## 窗口拖动
|
||
|
||
在v2中,使用`--wails-drag`属性来指示可以使用元素拖动窗口。在v3中,已将其替换
|
||
为`--webkit-app-region`,以更符合其他框架处理方式。`--webkit-app-region`属性可以
|
||
设置为以下任何值:
|
||
|
||
- `drag` - 可使用该元素拖动窗口
|
||
- `no-drag` - 该元素无法用于拖动窗口
|
||
|
||
我们本来希望使用`app-region`,但是在webkit在macOS上的`getComputedStyle`调用不支
|
||
持它。
|