5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-05 06:12:02 +08:00
wails/mkdocs-website/docs/zh/development/changes.md
2023-11-02 20:53:59 +11:00

14 KiB
Raw Blame History

v3的更改

!!! note 这是当前的无序更改脑升级。很快它将组织成一个更易读的格式。

选项

自v2以来应用程序选项已经进行了修订。

事件

在v3中有3种类型的事件

  • 应用程序事件
  • 窗口事件
  • 自定义事件

应用程序事件

应用程序事件是由应用程序发出的事件。这些事件包括macOS上的ApplicationDidFinishLaunching等本机事件。

窗口事件

窗口事件是由窗口发出的事件。这些事件包括macOS上的WindowDidBecomeMain等本机事件。还定义了常见事件,以便它们在跨平台上工作,例如WindowClosing

自定义事件

用户定义的事件称为WailsEvents。这是为了将它们与用于与浏览器通信的Event对象区分开来。WailsEvents现在是封装事件的对象。这包括事件名称数据和事件的源。

与WailsEvent关联的数据现在是单个值。如果需要多个值则可以使用struct。

事件回调和Emit函数签名

事件回调的签名(由OnOnceOnMultiple使用已更改。在v2中回调函数接收可选数据。在v3中回调函数接收包含与事件相关的所有数据的WailsEvent对象。

类似地,Emit函数已更改。它现在不再接受名称和可选数据,而是接受一个WailsEvent对象,它将发出该对象。

OffOffAll

在v2中OffOffAll调用将删除JS和Go中的事件。由于v3具有多窗口的特性因此已更改为这些方法仅适用于调用它们的上下文。例如如果你在一个窗口中调用Off它仅会删除该窗口的事件。如果你在Go中使用Off它只会删除Go的事件。

Hooks

事件钩子是v3中的新功能。它们允许您钩入事件系统并在发出某些事件时执行操作。例如您可以钩入WindowClosing事件,在窗口关闭之前执行一些清理操作。钩子可以在应用程序级别或窗口级别使用RegisterHook进行注册。应用程序级别适用于应用程序事件。仅当窗口级别钩子与其注册的窗口一起调用。

日志记录

在v2中日志记录会混淆因为应用程序日志和系统内部日志都使用相同的记录器。我们已经对此进行了简化

  • 内部日志现在使用标准的Go slog记录器处理。这是通过应用程序选项中的logger选项进行配置的。默认情况下,这使用tint记录器。
  • 现在可以通过新的log插件进行应用程序日志记录,它在底层使用slog。此插件提供了一个简单的用于记录到控制台的API。它在Go和JS中都可用。

开发人员注意事项

在Go中发出事件时它会将事件分派到本地的Go侦听器以及应用程序中的每个窗口。在JS中发出事件时它现在会将事件发送到应用程序。这将被处理就好像它是在Go中发出的但是发送者ID将是窗口的ID。

窗口

Window API在很大程度上保持不变但方法现在是在窗口实例而不是运行时上。一些值得注意的变化是

  • 窗口现在具有标识它们的名称。用于在发出事件时标识窗口。
  • 窗口上现在有更多以前不可用的方法,例如AbsolutePositionToggleDevTools
  • 窗口现在可以通过本机拖放接受文件。有关详细信息,请参阅拖放部分。

剪切板

剪贴板API已经简化。现在有一个单独的Clipboard对象,可以用于读取和写入剪贴板。Clipboard对象在Go和JS中都可用。SetText()用于设置文本,Text()用于获取文本。

绑定

绑定的工作方式与v2类似通过提供一种将结构方法绑定到前端的方式。这些可以在前端使用由wails3 generate bindings命令生成的绑定包装器来调用:

// @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哈希算法计算的。这是为了防止方法名称在生产构建中被暴露出来。在调试模式下方法ID与计算的方法ID一起记录以帮助调试。如果您希望增加额外的混淆层可以使用BindAliases选项。这允许您指定别名ID与方法ID的映射。当前端使用ID调用方法时方法ID将首先在别名映射中查找匹配项。如果找不到它将假定是标准方法ID并尝试以通常的方式查找方法。

示例:

	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,那么可以使用不安全的wails.CallByName()方法。此方法接受要调用的方法的完全限定名称和要传递给它的参数。示例:

```go
wails.CallByName("main.GreetService.Greet", "world!")
```

!!! danger

这仅作为开发的便利方法提供。不建议在生产中使用此方法。

对话框

对话框现在在JavaScript中可用

Windows

Windows中的对话框按钮是不可配置的根据对话框的类型是恒定的。要在按下按钮时触发回调请创建一个具有与您希望附加回调的按钮相同名称的按钮。示例创建一个标签为“确定”的按钮并使用OnClick()方法设置回调方法:

        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事件。属性的值应为要发出的事件的名称。

示例:

<button data-wml-event="myevent">Click Me</button>

有时您需要用户确认操作。可以通过向元素添加data-wml-confirm属性来完成。此属性的值将是要显示给用户的消息。

示例:

<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方法。属性的值应为要调用的方法的名称。方法名称应与导出的方法的名称完全匹配。

<button data-wml-window="Close">Close Window</button>

data-wml-trigger

此属性指定应触发操作的javascript事件。默认为click

<button data-wml-event="hover-box" data-wml-trigger="mouseover">
  Hover over me!
</button>

系统托盘

Wails 3附带了一个内置的系统托盘。这是一个完全功能的系统托盘旨在尽可能简单地使用。可以设置托盘的图标、工具提示和菜单。还可以“附加”窗口到系统托盘。这样做将提供以下功能

  • 单击托盘图标会切换窗口可见性
  • 右键单击托盘将打开菜单(如果有)

在macOS上如果没有附加的窗口则托盘将使用显示菜单的默认方法任何按钮。如果有附加的窗口但没有菜单则托盘将切换窗口而不管按下的按钮如何。

插件

插件是扩展Wails应用程序功能的一种方式。

创建插件

插件是符合以下接口的标准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中枚举通常被定义为类型和一组常量。例如

type MyEnum int

const (
    MyEnumOne MyEnum = iota
    MyEnumTwo
    MyEnumThree
)

由于Go和JavaScript之间的不兼容性无法以这种方式使用自定义类型。最好的策略是为float64使用类型别名

type MyEnum = float64

const (
    MyEnumOne MyEnum = iota
    MyEnumTwo
    MyEnumThree
)

在Javascript中您可以使用以下代码

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消息。该函数应具有以下签名

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调用不支持它。