前端執行階段
用於前端整合的 Wails JavaScript 執行階段套件
Wails 前端執行階段是 Wails 應用程式的標準程式庫,提供多項可在應用程式中使用的功能,包括:
- 視窗管理
- 對話方塊
- 瀏覽器整合
- 剪貼簿
- 選單
- 系統資訊
- 事件
- 內容選單
- 螢幕
- WML(Wails 標記語言)
Go 與前端之間的整合需要使用此執行階段。整合執行階段有2種方式:
- 使用
@wailsio/runtime套件 - 使用預先建置的套件組合
使用 npm 套件
@wailsio/runtime套件是一個 JavaScript 套件,可讓前端存取 Wails 執行階段。所有標準範本都使用此套件,這也是將執行階段整合至應用程式的建議方式。使用@wailsio/runtime套件時,只會納入您實際使用的執行階段部分。
此套件已在 npm 上提供,可使用以下方式安裝:
npm install --save @wailsio/runtime
使用預先建置的套件組合
有些專案不使用 JavaScript 打包工具,可能偏好使用預先建置的執行階段套件組合版本。您可以在本機使用以下命令產生此版本:
wails3 generate runtime
此命令會在目前目錄中輸出runtime.js檔案(以及runtime.debug.js檔案)。這是 ES 模組,應用程式指令碼可像匯入 npm 套件一樣匯入它;此外,其 API 也會匯出至全域 window 物件,因此較簡單的應用程式可以如下使用:
<html>
<head>
<script type="module" src="./runtime.js"></script>
<script>
window.onload = function () {
wails.Window.SetTitle("A new window title");
}
</script>
</head>
<!--- ... -->
</html>初始化
除了 API 函式外,執行階段也支援內容選單和視窗拖曳。只有在執行階段完成初始化後,這些功能才會如預期運作。即使您不使用 API,也請務必在前端程式碼中的某處加入僅為觸發副作用的匯入陳述式:
import "@wailsio/runtime";打包工具應會偵測到副作用,並在組建中納入所有必要的初始化程式碼。
用於型別化事件的 Vite 外掛程式
執行階段內含 Vite 外掛程式,可在開發期間為型別化事件啟用 HMR(熱模組替換)支援。
設定
將此外掛程式加入您的vite.config.ts:
import { defineConfig } from 'vite'
import wails from '@wailsio/runtime/plugins/vite'
export default defineConfig({
plugins: [wails()],
})優點
- 自動重新載入:執行
wails3 generate bindings時,系統會自動重新產生並載入事件繫結 - 開發模式:可與
wails3 dev無縫搭配,立即套用更新 - 型別安全:完整支援 TypeScript,並提供自動完成和型別檢查
搭配事件註冊使用
在 Go 中註冊事件:
type UserData struct {
ID string
Name string
}
func init() {
application.RegisterEvent[UserData]("user-updated")
}產生繫結:
wails3 generate bindings
# Or, to include TypeScript definitions
wails3 generate bindings -ts
# For more options, see:
wails3 generate bindings -help
在前端使用型別化事件:
import { Events } from '@wailsio/runtime'
import { UserUpdated } from './bindings/events'
// Type-safe event with autocomplete
Events.Emit(UserUpdated({
ID: "123",
Name: "John Doe"
}))API 參考
執行階段依模組組織,每個模組各自提供特定功能。只匯入您需要的項目:
import { Events, Window, Clipboard } from '@wailsio/runtime'事件
用於 Go 與 JavaScript 之間通訊的事件系統。
On()
為事件註冊回呼函式。
function On(eventName: string, callback: (event: WailsEvent) => void): () => void
function On<T>(eventType: EventType<T>, callback: (event: WailsEvent<T>) => void): () => void傳回:取消訂閱函式
範例:
import { Events } from '@wailsio/runtime'
// Basic event listening
const unsubscribe = Events.On('user-logged-in', (event) => {
console.log('User:', event.data.username)
})
// With typed events (TypeScript)
import { UserLogin } from './bindings/events'
Events.On(UserLogin, (event) => {
// event.data is typed as UserLoginData
console.log('User:', event.data.username)
})
// Later: unsubscribe()Once()
註冊只執行一次的回呼函式。
function Once(eventName: string, callback: (event: WailsEvent) => void): () => void
function Once<T>(eventType: EventType<T>, callback: (event: WailsEvent<T>) => void): () => void範例:
import { Events } from '@wailsio/runtime'
Events.Once('app-ready', () => {
console.log('App initialized')
})Emit()
將事件發送至 Go 後端或其他視窗。
function Emit(name: string, data?: any): Promise<boolean>
function Emit<T>(event: Event<T>): Promise<boolean>傳回:一個 Promise;若事件遭取消,會解析為true,否則解析為false
範例:
import { Events } from '@wailsio/runtime'
// Basic event emission
const wasCancelled = await Events.Emit('button-clicked', { buttonId: 'submit' })
// With typed events (TypeScript)
import { UserLogin } from './bindings/events'
const cancelled = await Events.Emit(UserLogin({
UserID: "123",
Username: "john_doe",
LoginTime: new Date().toISOString()
}))
if (cancelled) {
console.log('Login was cancelled by a hook')
}Off()
移除事件監聽器。
function Off(...eventNames: string[]): void範例:
import { Events } from '@wailsio/runtime'
Events.Off('user-logged-in', 'user-logged-out')OffAll()
移除所有事件監聽器。
function OffAll(): void視窗
視窗管理方法。預設匯出的是目前視窗。
import { Window } from '@wailsio/runtime'
// Current window
await Window.SetTitle('New Title')
await Window.Center()
// Get another window
const otherWindow = Window.Get('secondary')
await otherWindow.Show()可見性
Show()-顯示視窗
function Show(): Promise<void>Hide()-隱藏視窗
function Hide(): Promise<void>Close() - 關閉視窗
function Close(): Promise<void>大小與位置
SetSize(width, height) - 設定視窗大小
function SetSize(width: number, height: number): Promise<void>Size() - 取得視窗大小
function Size(): Promise<{ width: number, height: number }>SetPosition(x, y) - 設定絕對位置
function SetPosition(x: number, y: number): Promise<void>Position() - 取得絕對位置
function Position(): Promise<{ x: number, y: number }>Center() - 將視窗置中
function Center(): Promise<void>範例:
import { Window } from '@wailsio/runtime'
// Resize and center
await Window.SetSize(800, 600)
await Window.Center()
// Get current size
const { width, height } = await Window.Size()視窗狀態
Minimise() - 將視窗最小化
function Minimise(): Promise<void>Maximise() - 將視窗最大化
function Maximise(): Promise<void>Fullscreen() - 進入全螢幕模式
function Fullscreen(): Promise<void>Restore() - 從最小化、最大化或全螢幕狀態還原
function Restore(): Promise<void>IsMinimised() - 檢查視窗是否已最小化
function IsMinimised(): Promise<boolean>IsMaximised() - 檢查視窗是否已最大化
function IsMaximised(): Promise<boolean>IsFullscreen() - 檢查視窗是否處於全螢幕模式
function IsFullscreen(): Promise<boolean>視窗屬性
SetTitle(title) - 設定視窗標題
function SetTitle(title: string): Promise<void>Name() - 取得視窗名稱
function Name(): Promise<string>SetBackgroundColour(r, g, b, a) - 設定背景顏色
function SetBackgroundColour(r: number, g: number, b: number, a: number): Promise<void>SetAlwaysOnTop(alwaysOnTop) - 讓視窗保持在最上層
function SetAlwaysOnTop(alwaysOnTop: boolean): Promise<void>SetResizable(resizable) - 設定視窗可調整大小
function SetResizable(resizable: boolean): Promise<void>焦點與螢幕
Focus() - 將焦點移至視窗
function Focus(): Promise<void>IsFocused() - 檢查視窗是否具有焦點
function IsFocused(): Promise<boolean>GetScreen() - 取得視窗所在的螢幕
function GetScreen(): Promise<Screen>內容
Reload() - 重新載入頁面
function Reload(): Promise<void>ForceReload() - 強制重新載入頁面(清除快取)
function ForceReload(): Promise<void>縮放
SetZoom(level) - 設定縮放層級
function SetZoom(level: number): Promise<void>GetZoom() - 取得縮放層級
function GetZoom(): Promise<number>ZoomIn() - 放大
function ZoomIn(): Promise<void>ZoomOut() - 縮小
function ZoomOut(): Promise<void>ZoomReset() - 將縮放重設為100%
function ZoomReset(): Promise<void>列印
Print() - 開啟原生列印對話方塊
function Print(): Promise<void>範例:
import { Window } from '@wailsio/runtime'
// Open print dialog for current window
await Window.Print()注意:這會開啟作業系統的原生列印對話方塊,讓使用者選擇印表機設定並列印目前視窗的內容。window.print()在 WebView 中可能無法運作,而此方法使用平台的原生列印 API。
剪貼簿
剪貼簿操作。
SetText()
設定剪貼簿文字。
function SetText(text: string): Promise<void>範例:
import { Clipboard } from '@wailsio/runtime'
await Clipboard.SetText('Hello from Wails!')Text()
取得剪貼簿文字。
function Text(): Promise<string>範例:
import { Clipboard } from '@wailsio/runtime'
const clipboardText = await Clipboard.Text()
console.log('Clipboard:', clipboardText)系統
用於直接與後端通訊的低階系統方法。
invoke()
將原始訊息直接傳送至後端。此操作會略過標準繫結系統,並由應用程式選項中的RawMessageHandler處理。
function invoke(message: any): void範例:
import { System } from '@wailsio/runtime'
// Send a raw message to the backend
System.invoke('my-custom-message')
// Send structured data as JSON
System.invoke(JSON.stringify({ action: 'update', value: 42 }))如需更多詳細資訊,請參閱原始訊息指南。
應用程式
應用程式層級的方法。
Show()
顯示所有應用程式視窗。
function Show(): Promise<void>Hide()
隱藏所有應用程式視窗。
function Hide(): Promise<void>Quit()
退出應用程式。
function Quit(): Promise<void>範例:
import { Application } from '@wailsio/runtime'
// Add quit button
document.getElementById('quit-btn').addEventListener('click', async () => {
await Application.Quit()
})瀏覽器
在預設瀏覽器中開啟 URL。
OpenURL()
在系統瀏覽器中開啟 URL。
function OpenURL(url: string | URL): Promise<void>範例:
import { Browser } from '@wailsio/runtime'
await Browser.OpenURL('https://wails.io')螢幕
螢幕資訊與管理。
GetAll()
取得所有螢幕。
function GetAll(): Promise<Screen[]>GetPrimary()
取得主要螢幕。
function GetPrimary(): Promise<Screen>GetCurrent()
取得目前作用中的螢幕。
function GetCurrent(): Promise<Screen>Screen 介面:
interface Screen {
ID: string
Name: string
ScaleFactor: number
X: number
Y: number
Size: { Width: number, Height: number }
Bounds: { X: number, Y: number, Width: number, Height: number }
WorkArea: { X: number, Y: number, Width: number, Height: number }
IsPrimary: boolean
Rotation: number
}範例:
import { Screens } from '@wailsio/runtime'
// List all screens
const screens = await Screens.GetAll()
screens.forEach(screen => {
console.log(`${screen.Name}: ${screen.Size.Width}x${screen.Size.Height}`)
})
// Get primary screen
const primary = await Screens.GetPrimary()
console.log('Primary screen:', primary.Name)對話方塊
從 JavaScript 顯示作業系統原生對話方塊。
Info()
顯示資訊對話方塊。
function Info(options: MessageDialogOptions): Promise<string>範例:
import { Dialogs } from '@wailsio/runtime'
await Dialogs.Info({
Title: 'Success',
Message: 'Operation completed successfully!'
})Error()
顯示錯誤對話方塊。
function Error(options: MessageDialogOptions): Promise<string>Warning()
顯示警告對話方塊。
function Warning(options: MessageDialogOptions): Promise<string>Question()
顯示含自訂按鈕的詢問對話方塊。
function Question(options: MessageDialogOptions): Promise<string>範例:
import { Dialogs } from '@wailsio/runtime'
const result = await Dialogs.Question({
Title: 'Confirm Delete',
Message: 'Are you sure you want to delete this file?',
Buttons: [
{ Label: 'Delete', IsDefault: false },
{ Label: 'Cancel', IsDefault: true }
]
})
if (result === 'Delete') {
// Delete the file
}OpenFile()
顯示開啟檔案對話方塊。
function OpenFile(options: OpenFileDialogOptions): Promise<string | string[]>範例:
import { Dialogs } from '@wailsio/runtime'
const file = await Dialogs.OpenFile({
Title: 'Select Image',
Filters: [
{ DisplayName: 'Images', Pattern: '*.png;*.jpg;*.jpeg' },
{ DisplayName: 'All Files', Pattern: '*.*' }
]
})
if (file) {
console.log('Selected:', file)
}SaveFile()
顯示儲存檔案對話方塊。
function SaveFile(options: SaveFileDialogOptions): Promise<string>WML(Wails 標記語言)
WML 為常見操作提供宣告式屬性。請將屬性新增至 HTML 元素:
屬性
wml-event - 點擊時發出事件
<button wml-event="save-clicked">Save</button>wml-window - 呼叫視窗方法
<button wml-window="Close">Close Window</button>
<button wml-window="Minimise">Minimize</button>wml-target-window - 指定 wml-window 的目標視窗
<button wml-window="Show" wml-target-window="settings">
Show Settings
</button>wml-openurl - 在瀏覽器中開啟 URL
<a href="#" wml-openurl="https://wails.io">Visit Wails</a>wml-confirm - 執行操作前顯示確認對話方塊
<button wml-window="Close" wml-confirm="Are you sure you want to close?">
Close
</button>範例:
<div>
<button wml-event="save-clicked">Save</button>
<button wml-window="Minimise">Minimize</button>
<button wml-window="Close" wml-confirm="Close window?">Close</button>
<a href="#" wml-openurl="https://github.com/wailsapp/wails">GitHub</a>
</div>完整範例
import { Events, Window, Clipboard, Dialogs, Screens } from '@wailsio/runtime'
// Listen for events from Go
Events.On('data-updated', (event) => {
console.log('Data:', event.data)
updateUI(event.data)
})
// Window management
document.getElementById('center-btn').addEventListener('click', async () => {
await Window.Center()
})
document.getElementById('fullscreen-btn').addEventListener('click', async () => {
const isFullscreen = await Window.IsFullscreen()
if (isFullscreen) {
await Window.UnFullscreen()
} else {
await Window.Fullscreen()
}
})
// Clipboard operations
document.getElementById('copy-btn').addEventListener('click', async () => {
await Clipboard.SetText('Copied from Wails!')
})
// Dialog with confirmation
document.getElementById('delete-btn').addEventListener('click', async () => {
const result = await Dialogs.Question({
Title: 'Confirm',
Message: 'Delete this item?',
Buttons: [
{ Label: 'Delete' },
{ Label: 'Cancel', IsDefault: true }
]
})
if (result === 'Delete') {
await Events.Emit('delete-item', { id: currentItemId })
}
})
// Screen information
const screens = await Screens.GetAll()
console.log(`Detected ${screens.length} screen(s)`)
screens.forEach(screen => {
console.log(`- ${screen.Name}: ${screen.Size.Width}x${screen.Size.Height}`)
})最佳實務
✅ 建議做法
- 選擇性匯入 - 僅匯入所需項目
- 處理 Promise - 所有方法都會傳回 Promise
- 對簡單操作使用 WML - 比 JavaScript 更簡潔
- 檢查傳回值 - 對話方塊尤其如此
- 取消訂閱事件 - 完成後進行清理
❌ 請勿這樣做
- 不要忘記 await - 大多數方法都是非同步的
- 不要阻塞 UI - 正確使用 async/await
- 不要忽略錯誤 - 一律處理 Promise 拒絕
TypeScript 支援
執行階段包含完整的 TypeScript 型別定義:
import { Events, Window } from '@wailsio/runtime'
Events.On('custom-event', (event) => {
// TypeScript knows event.data, event.name, event.sender
console.log(event.data)
})
// All methods are fully typed
const size: { width: number, height: number } = await Window.Size()