调用能力

在 Electron 中我们可以通过ipc进行页面调用nodejs的能力,wails 也提供了类似的方案:Runtime & Bindings。

这两者,在当你运行或构建的时候,这两个目录会自动生成到前端里,然后前端就可以使用 Go语言听过的能力了。

Runtime

runtime 是 Wails 内置封装好并对前端还曝漏的api,包含常用能力,比如 dialogs、events、window、clipboard 等。

前端中可以直接导入使用,比如下边的打开文件选择器:

import { OpenFile } from '@wailsio/runtime/dialogs'

const path = await OpenFile({
  Title: '选择图片',
  Filters: [
    {
      DisplayName: 'Images',
      Pattern: '*.png;*.jpg;*.jpeg;*.webp;*.gif',
    },
  ],
  AllowsMultipleSelection: false,
})

Bindings

同 Runtime,Bindings 也是封装好并对前端还曝漏的api,只不够这个封装是我们自己封装,一般多用于业务场景。

后台层面

先定义好业务逻辑

greet_service.go
type GreetService struct{}
func (g *GreetService) Greet(name string) string {
	return "Hello " + name + "!"
}

在将其注册进 Wails,比如

main.go
application.New(application.Options{
    Name:        "demo-poject",
    Description: "A demo of using raw HTML & CSS",
    Services: []application.Service{
        application.NewService(&GreetService{}),
    }
})

这个对象要被注册进 Wails,方法名是大写,则就会自动生成到Bindings中!

前端层面

前端这边直接调用即可

myButton.addEventListener('click', async () => {
    let name = (nameElement as HTMLInputElement).value
    try {
        resultElement.innerText = await GreetService.Greet(name);
    } catch (err) {
        console.error(err);
    }
});

其它

服务器里使用app

service 里拿 app 很常见。Wails 里main.go的 app 可以理解成宿主能力入口,service 如果要发事件、开 dialog、操作窗口、读配置、调系统能力,持有它很正常,类似 Electron 主进程里封装 IPC handler 时用 app / BrowserWindow / dialog。

但是Wails 又不像 Electron 那么“到处 import 一个全局 app 就能用”。毕竟 Go 语言推什么都要从搬砖开始的思维,所以在main注册service的时候我们可以手动传递

greet_service.go
type GreetService struct{ app *application.App }
func (g *GreetService) Greet(name string) string {
    // 比如:新开一个窗口
    g.app.Window.NewWithOptions(application.WebviewWindowOptions{
		Title: "New Window",
		URL:   "/",
		Width:  800,
		Height: 600,
	})
	return "Hello " + name + "!"
}
main.go
application.New(application.Options{
    Name:        "demo-poject",
    Description: "A demo of using raw HTML & CSS"
})
app.RegisterService(application.NewService(&GreetService(app)))