Go Wails 桌面開發(fā)之 Go 與 Preact 如何協(xié)作通信?
上一篇文章里我們簡單的了解了Wails,在本篇文章里將帶你從0開始,借助 Wails框架構(gòu)建一個前后端分離的Todo應(yīng)用,前端用Preact,后端使用Go,并講解它們之間的通信機制與數(shù)據(jù)傳遞方式。閑話少說,開始今天的內(nèi)容,let's go!!!
Wails 框架如何工作?
在Wails中,前端通過WebView渲染頁面,后端通過Go提供邏輯支持。它的工作流程如下:
- 前端使用Vite(也可以是其他的)構(gòu)建(React/Preact/Vue 等)。
- Go 后端通過 Bind綁定結(jié)構(gòu)體或方法。
- 前端調(diào)用wailsjs/go/模塊名/方法名與后端通信(由Wails自動生成綁定文件)。
- Wails通過WebView (Windows/macOS/Linux) 將UI嵌入為桌面應(yīng)用。
通信簡圖如下:
用戶界面 (Preact)
│
▼
JS Bridge (Wails JS Runtime)
│
▼
Go 后端邏輯
構(gòu)建一個簡單的Todo應(yīng)用
我們使用wail init命令初始化一個名為todo的項目 ,命令具體如下所示:
wails init -n todo -t preact-ts
這里選擇的前端模版是preact-ts,它比較輕量級,語法上跟react可能不太一樣,但是整體相同。
項目創(chuàng)建好之后進入到項目目錄,創(chuàng)建todo目錄和todo.go文件,具體如下圖所示:
在todo.go文件里,鍵入如下代碼:
package todo
type Todo struct {
ID int `json:"id"`
Title string `json:"title"`
Done bool `json:"done"`
}
type TodoService struct {
todos []Todo
nextID int
}
func NewTodoService() *TodoService {
return &TodoService{
todos: []Todo{},
nextID: 1,
}
}
func (t *TodoService) GetTodos() []Todo {
return t.todos
}
func (t *TodoService) AddTodo(title string) Todo {
todo := Todo{
ID: t.nextID,
Title: title,
Done: false,
}
t.todos = append(t.todos, todo)
t.nextID++
return todo
}
func (t *TodoService) ToggleTodo(id int) []Todo {
for i, item := range t.todos {
if item.ID == id {
t.todos[i].Done = !item.Done
break
}
}
return t.todos
}
完事之后,我們需要將todo中的NewTodoService注冊到wails中,具體操作如下:
package main
import (
"embed"
"todo/todo"
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed all:frontend/dist
var assets embed.FS
func main() {
// Create an instance of the app structure
//app := NewApp() // 注釋掉wails生成的app
server := todo.NewTodoService()
// Create application with options
err := wails.Run(&options.App{
Title: "todo",
Width: 1024,
Height: 768,
AssetServer: &assetserver.Options{
Assets: assets,
},
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
//OnStartup: app.startup,
Bind: []interface{}{
server, // 將server實例注冊綁定到wails中
},
})
if err != nil {
println("Error:", err.Error())
}
}
這時候運行wails dev就可以將我們todo里寫的go代碼生成js,用于和前端進行一個綁定,當然了,一般實際開發(fā)中并不會使用wails dev來生成,而是使用wails generate module命令來生成。而生成的代碼都被放在了wailsjs/go目錄下,具體如下圖所示:
代碼生成好了之后我們編寫前端代碼,并在里面調(diào)用我們生成的go綁定代碼,具體如下所示:
import { h } from 'preact'
import { useEffect, useState } from 'preact/hooks'
import { AddTodo, GetTodos, ToggleTodo } from '../wailsjs/go/todo/TodoService'
interface Todo {
id: number
title: string
done: boolean
}
export default function App() {
const [todos, setTodos] = useState<Todo[]>([])
const [input, setInput] = useState('')
useEffect(() => {
refreshTodos()
}, [])
const refreshTodos = () => {
GetTodos().then(setTodos)
}
const add = () => {
if (!input) return
AddTodo(input).then(() => {
setInput('')
refreshTodos()
})
}
const toggle = (id: number) => {
ToggleTodo(id).then(setTodos)
}
return (
<div className="p-4">
<h1 className="text-2xl font-bold mb-4">?? Todo List</h1>
<input
className="border p-2 mr-2"
placeholder="Enter todo"
value={input}
onInput={(e: any) => setInput(e.target.value)}
/>
<button className="bg-blue-500 text-white p-2" onClick={add}>Add</button>
<ul className="mt-4">
{todos.map(todo => (
<li
key={todo.id}
className={`cursor-pointer ${todo.done ? 'line-through text-gray-500' : ''}`}
onClick={() => toggle(todo.id)}
>
{todo.title}
</li>
))}
</ul>
</div>
)
}
最后運行wails dev命令,讓我們來見證時刻的奇跡吧!!!
結(jié)語
Wails是前后端集成的利器。通過本文你了解了:
- Wails前后端的工作原理
- Go與Preact 如何通信
- 如何使用Wails快速搭建桌面級Todo應(yīng)用
看到這,各位帥哥靚女可能都明白了,這東西擺明換湯不換藥,這個跟平常前后端沒啥兩樣的,如同生氣的她,多提醒一下,多喝熱水對身體好。今天的內(nèi)容到此結(jié)束,感謝??您的收看??????,下次再見??