使用 wails(vue.js) 在 Go 中构建 web app(译文)| Go主题月

2,604 阅读4分钟

Alex

2019年5月6日,星期一

image.png

这篇文章是来自于视频 packagemain#6:使用Wails在Go中构建桌面应用程序

众所周知,Go 主要用于构建 API、web 后端和 CLI 工具。但有趣的是,Go 还可以用在我们可能不会想到的地方。

例如,我们可以使用 Wails 框架,用 Go 和 Vue.js 构建一个桌面应用程序。

这个框架是新的,仍处于测试阶段,但我很惊讶用它开发、构建和打包应用程序是多么容易。 Wails 提供了将 Go 代码和 web 前端打包成单个二进制文件的能力。wails CLI 通过处理项目创建、编译和绑定,使这一点变得简单。

APP

我们将建立一个非常简单的应用程序来实时显示我的机器的 CPU 使用情况。如果你有时间并且喜欢 Wails ,你可以想出一些更有创意和更复杂的东西。

安装

Wails CLI 可以通过 go get 安装。安装后使用 wails setup 命令进行设置。

go get github.com/wailsapp/wails/cmd/wails
wails setup

然后让我们用 cpustats 来启动我们的项目:

wails init
cd cpustats

我们的项目包括 Go 后端和 Vue.js 前端。main.go 将是我们的入口点,在这个入口中我们可以包含任何其他依赖项,还有 go.mod 文件用来管理它们。frontend 文件夹包含 Vue.js 组件,webpack 和 CSS。

概念

在后端和前端之间共享数据有两个主要组件:绑定和事件。

绑定是一种允许你将 Go 代码公开(绑定)到前端的方法。

此外,Wails 提供了一个统一事件系统。类似于 Javascript 的本地事件系统。这意味着,任何从 Go 或 Javascript 发送的事件都可以由双方接收。数据可以随任何事件一起传递。这允许你完成一些整洁的事情,比如让后台进程运行在 Go 中,并通知任何更新的前端。

后端

让我们首先开发一个后端部分以获取 CPU 使用情况,并使用 bind 方法将其发送到前端。

我们将创建一个新包并定义一个类型,我将把它公开(绑定)到前端。

//pkg/sys/sys.go:

package sys

import (
	"math"
	"time"

	"github.com/shirou/gopsutil/cpu"
	"github.com/wailsapp/wails"
)

// Stats .
type Stats struct {
	log *wails.CustomLogger
}

// CPUUsage .
type CPUUsage struct {
	Average int `json:"avg"`
}

// WailsInit .
func (s *Stats) WailsInit(runtime *wails.Runtime) error {
	s.log = runtime.Log.New("Stats")
	return nil
}

// GetCPUUsage .
func (s *Stats) GetCPUUsage() *CPUUsage {
	percent, err := cpu.Percent(1*time.Second, false)
	if err != nil {
		s.log.Errorf("unable to get cpu stats: %s", err.Error())
		return nil
	}

	return &CPUUsage{
		Average: int(math.Round(percent[0])),
	}
}

如果你的结构有一个 WailsInit 方法,Wails 会在启动时调用它。这允许您在启动主应用程序之前进行一些初始化。

main.go 中引入 sys 包,绑定 Stats 实例返回给前端:

package main

import (
	"github.com/leaanthony/mewn"
	"github.com/plutov/packagemain/cpustats/pkg/sys"
	"github.com/wailsapp/wails"
)

func main() {
	js := mewn.String("./frontend/dist/app.js")
	css := mewn.String("./frontend/dist/app.css")

	stats := &sys.Stats{}

	app := wails.CreateApp(&wails.AppConfig{
		Width:  512,
		Height: 512,
		Title:  "CPU Usage",
		JS:     js,
		CSS:    css,
		Colour: "#131313",
	})
	app.Bind(stats)
	app.Run()
}

前端

我们从 Go 绑定 stats 实例,那么它可以在 frontend 中被 window.backend.Stats 调用。如果我们想调用函数 GetCPUUsage() ,它将返回一个 Promise 。

window.backend.Stats.GetCPUUsage().then(cpu_usage => {
    console.log(cpu_usage);
})

为了将整个项目构建成单个二进制文件,我们应该运行 wails build, 添加 -d 标志可以构建一个可调试的版本。它将创建一个名称与项目名称匹配的二进制文件。

让我们通过简单地在屏幕上显示 CPU 使用率值来测试它是否有效:

wails build -d
./cpustats

事件

我们使用绑定将 CPU 使用率值发送到前端,现在让我们尝试不同的方法,让我们在后端创建一个计时器,它将使用事件方法在后台发送 CPU 使用率值。然后我们可以用 Javascript 订阅事件。

在 Go 中,我们可以使用 WailsInit 函数:

func (s *Stats) WailsInit(runtime *wails.Runtime) error {
	s.log = runtime.Log.New("Stats")

	go func() {
		for {
			runtime.Events.Emit("cpu_usage", s.GetCPUUsage())
			time.Sleep(1 * time.Second)
		}
	}()

	return nil
}

在 Vue.js 中我们可以在组件挂载(或其他地方)时订阅此事件:

mounted: function() {
    wails.events.on("cpu_usage", cpu_usage => {
        if (cpu_usage) {
            console.log(cpu_usage.avg);
        }
    });
}

测量条

使用测量条显示 CPU 使用情况会很好,因此我们将包含第三方依赖项,只需使用 npm 即可:

npm install --save apexcharts
npm install --save vue-apexcharts

然后导入 main.js 文件:

import VueApexCharts from 'vue-apexcharts'

Vue.use(VueApexCharts)
Vue.component('apexchart', VueApexCharts)
Now we can display our CPU Usage using apexcharts, and update the values of the component by receiving an event from Backend:

<template>
  <apexchart type="radialBar" :options="options" :series="series"></apexchart>
</template>

<script>
export default {
  data() {
    return {
      series: [0],
      options: {
        labels: ['CPU Usage']
      }
    };
  },
  mounted: function() {
    wails.events.on("cpu_usage", cpu_usage => {
      if (cpu_usage) {
        this.series = [ cpu_usage.avg ];
      }
    });
  }
};
</script>

要更改样式,我们可以直接修改 src/assets/css/main.css 或者在组件中定义它们。

最终构建和运行

wails build -d
./cpustats

image.png

结论

我非常喜欢使用 Wails,事件概念使你很容易控制应用程序的状态。

去看看吧 wails.app 或者在 Github 上 github.com/wailsapp/wails

GitHub 上本文的完整代码

原文连接:pliutau.com/wails-go-vu…