跳到主要内容
版本:v2.9.0

应用程序开发

使用 Wails 开发应用程序没有硬性规定,但有一些基本准则。

应用程序设置

默认模板使用的模式是,main.go 用于配置和运行应用程序,而 app.go 用于定义应用程序逻辑。

app.go 文件将定义一个结构体,该结构体具有两个方法,充当主应用程序的钩子。

app.go
type App struct {
ctx context.Context
}

func NewApp() *App {
return &App{}
}

func (a *App) startup(ctx context.Context) {
a.ctx = ctx
}

func (a *App) shutdown(ctx context.Context) {
}
  • 启动方法在 Wails 分配其所需的资源后立即调用,是创建资源、设置事件监听器以及应用程序在启动时需要的任何其他事物的理想位置。它被赋予一个 context.Context,通常保存在结构体字段中。此上下文对于调用 运行时 是必需的。如果此方法返回错误,应用程序将终止。在开发模式下,错误将输出到控制台。

  • 关闭方法将在 Wails 的关闭过程结束时调用。这是释放内存和执行任何关闭任务的理想位置。

main.go 文件通常包含对 wails.Run() 的单个调用,该调用接受应用程序配置。模板使用的模式是在调用 wails.Run() 之前,创建 app.go 中定义的结构体的实例,并将其保存在名为 app 的变量中。此配置是我们在其中添加回调的地方。

main.go
func main() {

app := NewApp()

err := wails.Run(&options.App{
Title: "My App",
Width: 800,
Height: 600,
OnStartup: app.startup,
OnShutdown: app.shutdown,
})
if err != nil {
log.Fatal(err)
}
}

有关应用程序生命周期钩子的更多信息,请参见 此处

绑定方法

您可能希望从前端调用 Go 方法。这通常通过在 app.go 中已经定义的结构体中添加公共方法来完成。

app.go
type App struct {
ctx context.Context
}

func NewApp() *App {
return &App{}
}

func (a *App) startup(ctx context.Context) {
a.ctx = ctx
}

func (a *App) shutdown(ctx context.Context) {
}

func (a *App) Greet(name string) string {
return fmt.Sprintf("Hello %s!", name)
}

在主应用程序配置中,Bind 键是我们告诉 Wails 我们想要绑定什么的地方。

main.go
func main() {

app := NewApp()

err := wails.Run(&options.App{
Title: "My App",
Width: 800,
Height: 600,
OnStartup: app.startup,
OnShutdown: app.shutdown,
Bind: []interface{}{
app,
},
})
if err != nil {
log.Fatal(err)
}
}

这将绑定我们 App 结构体中的所有公共方法(它永远不会绑定启动和关闭方法)。

在绑定多个结构体时处理上下文

如果您想为多个结构体绑定方法,但希望每个结构体都保留对上下文的引用,以便您可以使用运行时函数,一个好的模式是从 OnStartup 方法将上下文传递到您的结构体实例中。

func main() {

app := NewApp()
otherStruct := NewOtherStruct()

err := wails.Run(&options.App{
Title: "My App",
Width: 800,
Height: 600,
OnStartup: func(ctx context.Context){
app.SetContext(ctx)
otherStruct.SetContext(ctx)
},
OnShutdown: app.shutdown,
Bind: []interface{}{
app,
otherStruct
},
})
if err != nil {
log.Fatal(err)
}
}

您可能还想在结构体中使用枚举,并在前端为它们创建模型。在这种情况下,您应该创建一个包含所有可能的枚举值的数组,对枚举类型进行检测,并将其绑定到应用程序。

app.go
type Weekday string

const (
Sunday Weekday = "Sunday"
Monday Weekday = "Monday"
Tuesday Weekday = "Tuesday"
Wednesday Weekday = "Wednesday"
Thursday Weekday = "Thursday"
Friday Weekday = "Friday"
Saturday Weekday = "Saturday"
)

var AllWeekdays = []struct {
Value Weekday
TSName string
}{
{Sunday, "SUNDAY"},
{Monday, "MONDAY"},
{Tuesday, "TUESDAY"},
{Wednesday, "WEDNESDAY"},
{Thursday, "THURSDAY"},
{Friday, "FRIDAY"},
{Saturday, "SATURDAY"},
}

在主应用程序配置中,EnumBind 键是我们告诉 Wails 我们想要绑定枚举的地方。

main.go
func main() {

app := NewApp()

err := wails.Run(&options.App{
Title: "My App",
Width: 800,
Height: 600,
OnStartup: app.startup,
OnShutdown: app.shutdown,
Bind: []interface{}{
app,
},
EnumBind: []interface{}{
AllWeekdays,
},
})
if err != nil {
log.Fatal(err)
}
}

这会将缺少的枚举添加到您的 model.ts 文件中。

有关绑定的更多信息,请参见 此处

应用程序菜单

Wails 支持将菜单添加到您的应用程序。这是通过将 Menu 结构体传递到应用程序配置来完成的。通常使用一个返回 Menu 的方法,更常见的是,该方法是用于生命周期钩子的 App 结构体上的方法。

main.go
func main() {

app := NewApp()

err := wails.Run(&options.App{
Title: "My App",
Width: 800,
Height: 600,
OnStartup: app.startup,
OnShutdown: app.shutdown,
Menu: app.menu(),
Bind: []interface{}{
app,
},
})
if err != nil {
log.Fatal(err)
}
}

资产

Wails v2 处理资产的方式很棒,因为它没有处理!您只需要给 Wails 一个 embed.FS。如何获得它完全取决于您。您可以使用与普通模板类似的普通 html/css/js 文件。您可能有一些复杂的构建系统,这并不重要。

运行 wails build 时,它将检查项目根目录处的 wails.json 项目文件。项目文件中读取了两个键。

  • "frontend:install"
  • "frontend:build"

第一个(如果给出)将在 frontend 目录中执行,以安装节点模块。第二个(如果给出)将在 frontend 目录中执行,以构建前端项目。

如果这两个键都没有给出,那么 Wails 不会对前端做任何事情。它只期望 embed.FS

AssetsHandler

Wails v2 应用程序可以选择在 options.App 中定义一个 http.Handler,这允许挂钩到 AssetServer 以动态创建文件或处理 POST/PUT 请求。GET 请求始终首先由 assets FS 处理。如果 FS 未找到请求的文件,则请求将转发到 http.Handler 以进行服务。除 GET 以外的任何请求都将由 AssetsHandler 直接处理(如果指定)。也可以通过将 nil 指定为 Assets 选项来仅使用 AssetsHandler

内置开发服务器

运行 wails dev 将启动内置开发服务器,该服务器将在您的项目目录中启动一个文件观察程序。默认情况下,如果任何文件发生更改,wails 将检查它是否是应用程序文件(默认:.go,可以通过 -e 标志进行配置)。如果是,那么它将重建您的应用程序并重新启动它。如果更改的文件在资产中,它将在很短时间后发出重新加载命令。

开发服务器使用一种称为“去抖动”的技术,这意味着它不会立即重新加载,因为短时间内可能会更改多个文件。当发生触发器时,它会等待一段时间,然后发出重新加载命令。如果发生另一个触发器,它会再次重置为等待时间。默认情况下,此值为 100ms。如果此值不适合您的项目,可以使用 -debounce 标志进行配置。如果使用,此值将保存到您的项目配置中,并成为默认值。

外部开发服务器

一些框架附带自己的实时重新加载服务器,但它们将无法利用 Wails Go 绑定。在这种情况下,最好运行一个观察程序脚本,将项目重建到构建目录,Wails 将监视该目录。例如,请参阅使用 rollup 的默认 svelte 模板。

创建 React 应用程序

Create-React-App 项目的过程稍微复杂一些。为了支持实时前端重新加载,需要将以下配置添加到您的 wails.json 中。

  "frontend:dev:watcher": "yarn start",
"frontend:dev:serverUrl": "http://localhost:3000",

frontend:dev:watcher 命令将启动 Create-React-App 开发服务器(通常托管在端口 3000 上)。然后,frontend:dev:serverUrl 命令指示 Wails 在加载前端时从开发服务器提供资产,而不是从构建文件夹提供资产。除了上述内容外,还需要使用以下内容更新 index.html

    <head>
<meta name="wails-options" content="noautoinject" />
<script src="/wails/ipc.js"></script>
<script src="/wails/runtime.js"></script>
</head>

这是必需的,因为重建前端的观察程序命令会阻止 Wails 注入所需的脚本。这通过确保始终注入脚本来规避了该问题。使用此配置,可以运行 wails dev,它将适当地构建前端和后端,并启用热重载。此外,当从浏览器访问应用程序时,现在可以在应用程序的非压缩版本上使用 React 开发者工具,以进行直接调试。最后,为了加快构建速度,可以运行 wails dev -s 以跳过 Wails 对前端的默认构建,因为这是不必要的步骤。

Go 模块

默认的 Wails 模板生成一个 go.mod 文件,其中包含模块名称“changeme”。项目生成后,您应该将其更改为更合适的内容。