Введение
go-app
это программа, написанная с использованием технологии Go + WebAssemblyПрогрессивные веб-приложениябиблиотека. WebAssembly — это современный код, который может работать в современных браузерах. За последние два года технология WebAssembly сделала большой шаг вперед. Теперь мы можем писать код WebAssembly на языках высокого уровня, таких как C/C++/Rust/Go. я собирался представитьgo-app
Эта библиотека упрощает написание кода WebAssembly в Go.
быстрый в использовании
go-app
К языковой версии Go предъявляются более высокие требования (Go 1.14+), И должен использоватьGo module
. Создайте каталог и инициализируйтеGo Module
(Win10 + Гит Баш):
$ mkdir go-app && cd go-app
$ go mod init
Затем скачайте и установитеgo-app
Сумка:
$ go get -u -v github.com/maxence-charriere/go-app/v6
Что касаетсяGo module
Для подробного использования см. Fried Fish's.Перейти модули Ultimate вход.
Во-первых, мы собираемся написать программу WebAssembly:
package main
import "github.com/maxence-charriere/go-app/v6/pkg/app"
type Greeting struct {
app.Compo
name string
}
func (g *Greeting) Render() app.UI {
return app.Div().Body(
app.Main().Body(
app.H1().Body(
app.Text("Hello, "),
app.If(g.name != "",
app.Text(g.name),
).Else(
app.Text("World"),
),
),
),
app.Input().
Value(g.name).
Placeholder("What is your name?").
AutoFocus(true).
OnChange(g.OnInputChange),
)
}
func (g *Greeting) OnInputChange(src app.Value, e app.Event) {
g.name = src.Get("value").String()
g.Update()
}
func main() {
app.Route("/", &Greeting{})
app.Run()
}
существуетgo-app
используется вкомпонентыЧтобы разделить функциональные модули, каждая структура компонента должна быть встроенаapp.Compo
.组件要实现Render()
Метод, когда вам нужно отобразить компонент, вызывает этот метод, возвращает отображение страницы.go-app
использоватьДекларативный синтаксис, вы можете полностью писать HTML-страницы с помощью Go, а описанную выше часть рисования HTML легче понять. Приведенный выше код также реализует функцию поля ввода и добавляет к нему прослушиватель. Всякий раз, когда содержимое поля ввода изменяется,OnInputChange
будет вызван метод,g.Update()
вызовет повторный рендеринг компонента.
Наконец, смонтируйте компонент по пути/
начальство.
После написания программы WebAssembly ее необходимо кросс-компилировать в.wasm
документ:
$ GOARCH=wasm GOOS=js go build -o app.wasm
Если есть ошибка компиляции, используйтеgo version
Команда, чтобы проверить, является ли Go версией 1.14 или новее.
Далее нам нужно написать веб-программу Go, чтобы использовать это.app.wasm
:
package main
import (
"log"
"net/http"
"github.com/maxence-charriere/go-app/v6/pkg/app"
)
func main() {
h := &app.Handler{
Title: "Go-App",
Author: "dj",
}
if err := http.ListenAndServe(":8080", h); err != nil {
log.Fatal(err)
}
}
go-app
предоставилapp.Handler
структура, он автоматически найдет файлы в том же каталогеapp.wasm
(Именно поэтому для целевого файла установлено значениеapp.wasm
причина). Затем мы скомпилируем сгенерированныйapp.wasm
Поместите его в тот же каталог и выполните программу:
$ go run main.go
Дисплей по умолчанию"Hello World"
:
После ввода в поле ввода дисплей изменится:
можно увидеть,go-app
Установите для нас некоторые основные стили, веб-иконки и т. д.
простой принцип
Эта диаграмма на GitHub прекрасно иллюстрирует поток выполнения HTTP-запроса:
Запросы пользователей на первом местеapp.Handler
слой и он пойдетapp.wasm
Выполните соответствующую логику маршрутизации и перейдите на диск, чтобы найти статические файлы. ответ черезapp.Handler
Перевод возвращается пользователю. пользователи видятapp.wasm
Рендеринг страницы. Фактически, в этой статье нам нужно только написать веб-программу GO, после каждой записи новой Webassembly, скопируйте новые файлы для компиляции сгенерированного App.wasm Rerun Далее процедуры веб-каталога. Уведомление,Если странице не удалось обновить кеш, это может быть вызвано тем, что вы можете попробовать очистить кеш браузера..
компоненты
Настроить компонент легко, просто добавьтеapp.Compo
Его можно встроить в структуру. выполнитьRender()
методы определяют внешний вид компонента, фактическиapp.Compo
Существует внешний вид по умолчанию, который мы можем просмотреть следующим образом:
func main() {
app.Route("/app", &app.Compo{})
app.Run()
}
Компилировать и генерироватьapp.wasm
После этого начальную программу Go Web модифицировать не нужно, достаточно запустить ее напрямую и открыть браузер для просмотра:
обработка событий
существуетбыстрый старт, мы также рассмотрели, как использовать события. Используйте декларативный синтаксисapp.Input().OnChange(handler)
Вы можете отслеживать изменения контента. Обработчик события должен бытьfunc (src app.Value, e app.Event)
тип,app.Value
является триггерным объектом,app.Event
является содержанием события. пройти черезapp.Value
Мы можем получить такую информацию, как содержимое поля ввода, параметры поля выбора и т. д.app.Event
Вы можете получить информацию о событии, будь то событие мыши, событие клавиатуры или другие события:
type ShowSelect struct {
app.Compo
option string
}
func (s *ShowSelect) Render() app.UI {
return app.Div().Body(
app.Main().Body(
app.H1().Body(
app.If(s.option == "",
app.Text("Please select!"),
).Else(
app.Text("You've selected "+s.option),
),
),
),
app.Select().Body(
app.Option().Body(
app.Text("apple"),
),
app.Option().Body(
app.Text("orange"),
),
app.Option().Body(
app.Text("banana"),
),
).
OnChange(s.OnSelectChange),
)
}
func (s *ShowSelect) OnSelectChange(src app.Value, e app.Event) {
s.option = src.Get("value").String()
s.Update()
}
func main() {
app.Route("/", &ShowSelect{})
app.Run()
}
Приведенный выше код отображает поле выбора, и при изменении параметра текст, отображаемый выше, изменится соответствующим образом. Изначально:
После выбора:
вложенные компоненты
Компоненты могут быть вложенными, т.е. использовать один компонент внутри другого. Визуализируйте внутренний компонент как часть внешнего компонента:
type Greeting struct {
app.Compo
}
func (g *Greeting) Render() app.UI {
return app.P().Body(
app.Text("Hello, "),
&Name{name: "dj"},
)
}
type Name struct {
app.Compo
name string
}
func (n *Name) Render() app.UI {
return app.Text(n.name)
}
func main() {
app.Route("/", &Greeting{})
app.Run()
}
Приведенный выше код находится в компонентеGreeting
встроенный вName
компонент, работает шоу:
жизненный цикл
go-app
Предоставляет функции ловушек для 3 жизненных циклов компонентов:
-
OnMount
: вызывается, когда компонент вставлен в DOM; -
OnNav
: вызывается при загрузке и обновлении страницы, на которой находится компонент; -
OnDismount
: вызывается при удалении компонента со страницы.
Например:
type Foo struct {
app.Compo
}
func (*Foo) Render() app.UI {
return app.P().Body(
app.Text("Hello World"),
)
}
func (*Foo) OnMount() {
fmt.Println("component mounted")
}
func (*Foo) OnNav(u *url.URL) {
fmt.Println("component navigated:", u)
}
func (*Foo) OnDismount() {
fmt.Println("component dismounted")
}
func main() {
app.Route("/", &Foo{})
app.Run()
}
Скомпилируйте и запустите, откройте страницу в браузере, откройтеконсоль браузераНаблюдайте за выводом:
component mounted
component navigated: http://localhost:8080/
писать HTML
В предыдущем примере мы видели, как использоватьДекларативный синтаксисПишите HTML-страницы.go-app
Соответствующие типы предусмотрены для всех стандартных элементов HTML. Названия методов, создающих эти объекты, тоже легче запомнить, то есть первая буква имени элемента пишется с большой буквы. какapp.Div()
Создаватьdiv
элемент,app.P()
Создаватьp
элемент,app.H1()
Создаватьh1
элементы и т.д. существуетgo-app
, эти структуры предоставляют соответствующие интерфейсы для использования разработчиками, такие какdiv
соответствоватьHTMLDiv
интерфейс:
type HTMLDiv interface {
Body(nodes ...Node) HTMLDiv
Class(v string) HTMLDiv
ID(v string) HTMLDiv
Style(k, v string) HTMLDiv
OnClick(h EventHandler) HTMLDiv
OnKeyPress(h EventHandler) HTMLDiv
OnMouseOver(h EventHandler) HTMLDiv
}
Вы можете видеть, что каждый метод возвращает этоHTMLDiv
сама, так что поддержитецепной вызов. Вызовите эти методы, чтобы установить различные аспекты элемента:
-
Class
: добавить класс CSS; -
ID
: установить атрибут id; -
Style
: установить встроенный стиль; -
Body
: Установите содержимое элемента, которое может быть вложено по желанию.div
содержитh1
иp
,p
содержитimg
Ждать;
И установить слушатели событий:
-
OnClick
: событие щелчка; -
OnKeyPress
: ключевое событие; -
OnMouseOver
: Наведите указатель мыши на событие.
Например следующий код:
app.Div().Body(
app.H1().Body(
app.Text("Title"),
),
app.P().ID("id").
Class("content").Body(
app.Text("something interesting"),
),
)
Эквивалент HTML-кода:
<div>
<h1>title</h1>
<p id="id" class="content">
something interesting
</p>
</div>
Родной элемент
мы можемapp.Raw()
Пишите HTML-код прямо вapp.Raw()
создаст соответствующийapp.UI
возвращение:
svg := app.Raw(`
<svg width="100" height="100">
<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
</svg>
`)
Но такой способ написания небезопасен, потому что структура HTML не проверяется.
состояние
В примере мы имели в начале использования условных операторов, условных операторов, соответствующих трем методам:If()/ElseIf()/Else()
.
If
иElseIf
Получает два параметра, первый параметрbool
ценность. еслиtrue
, второй параметр (типаapp.UI
), иначе не отображается.
Else
Должен бытьIf
илиElseIf
После использования, если ни одно из предыдущих условий не выполнено, отобразить входящийElse
методapp.UI
:
type ScoreUI struct {
app.Compo
score int
}
func (c *ScoreUI) Render() app.UI {
return app.Div().Body(
app.If(c.score >= 90,
app.H1().
Style("color", "green").
Body(
app.Text("Good!"),
),
).ElseIf(c.score >= 60,
app.H1().
Style("color", "orange").
Body(
app.Text("Pass!"),
),
).Else(
app.H1().
Style("color", "red").
Body(
app.Text("fail!"),
),
),
app.Input().
Value(c.score).
Placeholder("Input your score?").
AutoFocus(true).
OnChange(c.OnInputChange),
)
}
func (c *ScoreUI) OnInputChange(src app.Value, e app.Event) {
score, _ := strconv.ParseUint(src.Get("value").String(), 10, 32)
c.score = int(score)
c.Update()
}
func main() {
app.Route("/", &ScoreUI{})
app.Run()
}
Выше мы отображаем соответствующий текст в соответствии с введенным счетом,90
и выше показаны зеленымGood!
,60-90
между апельсиномPass!
, меньше, чем60
показать красныйFail!
. Ниже приведен текущий результат:
Range
Предположим, мы хотим написать список HTML, в настоящее время есть ломтик строки. Если писать слишком громоздкое и негибкое, и склонна к ошибке. Затем вы можете использоватьRange()
Метод:
type RangeUI struct {
app.Compo
name string
}
func (*RangeUI) Render() app.UI {
langs := []string{"Go", "JavaScript", "Python", "C"}
return app.Ul().Body(
app.Range(langs).Slice(func(i int) app.UI {
return app.Li().Body(
app.Text(langs[i]),
)
}),
)
}
func main() {
app.Route("/", &RangeUI{})
app.Run()
}
Range()
можно нарезать илиmap
Генерируетapp.UI
, а затем расположите плитку над элементомBody()
метод.
результат операции:
контекстное меню
существуетgo-app
, мы можем легко настроить всплывающее меню, вызываемое правой кнопкой мыши, и написать ответы для пунктов меню:
type ContextMenuUI struct {
app.Compo
name string
}
func (c *ContextMenuUI) Render() app.UI {
return app.Div().Body(
app.Text("Hello, World"),
).OnContextMenu(c.OnContextMenu)
}
func (*ContextMenuUI) OnContextMenu(src app.Value, event app.Event) {
event.PreventDefault()
app.NewContextMenu(
app.MenuItem().
Label("item 1").
OnClick(func(src app.Value, e app.Event) {
fmt.Println("item 1 clicked")
}),
app.MenuItem().Separator(),
app.MenuItem().
Label("item 2").
OnClick(func(src app.Value, e app.Event) {
fmt.Println("item 2 clicked")
}),
)
}
func main() {
app.Route("/", &ContextMenuUI{})
app.Run()
}
мы вOnContextMenu
позвонил вevent.PreventDefault()
Предотвращает всплывающее меню по умолчанию. Смотрите бегущий результат:
Нажмите на пункт меню и наблюдайте за выводом консоли~
app.Handler
Выше мы используемgo-app
Встроенныйapp.Handler
Обработка клиентских запросов. Мы просто устанавливаем простые две свойстваAuthor
иTitle
.app.Handler
Есть много других полей, которые можно настроить:
type Handler struct {
Author string
BackgroundColor string
CacheableResources []string
Description string
Env Environment
Icon Icon
Keywords []string
LoadingLabel string
Name string
RawHeaders []string
RootDir string
Scripts []string
ShortName string
Styles []string
ThemeColor string
Title string
UseMinimalDefaultStyles bool
Version string
}
-
Icon
: установить значок приложения; -
Styles
: файл стилей CSS; -
Scripts
: Файл сценария JS.
Файлы CSS и JS должны быть вapp.Handler
заявление в. Ниже приведен примерapp.Handler
:
h := &app.Handler{
Name: "Luck",
Author: "Maxence Charriere",
Description: "Lottery numbers generator.",
Icon: app.Icon{
Default: "/web/icon.png",
},
Keywords: []string{
"EuroMillions",
"MEGA Millions",
"Powerball",
},
ThemeColor: "#000000",
BackgroundColor: "#000000",
Styles: []string{
"/web/luck.css",
},
Version: "wIKiverSiON",
}
Код этой статьи
Код WebAssembly для этой статьи находится в отдельном каталоге. Демонстрационный код Go Web находится в веб-каталоге. Сначала введите каталог и скомпилируйте с помощью следующей команды:
$ GOARCH=wasm GOOS=js go build -o app.wasm
затем будет генерироватьapp.wasm
скопировать вweb
содержание:
$ cp app.wasm ../web/
Перейдите в веб-каталог и запустите сервер:
$ cd ../web/
$ go run main.go
Суммировать
В этой статье описывается, как использоватьgo-app
Написание веб-приложений на основе WebAssembly. Некоторые люди могут подумать,go-app
То, как вы пишете HTML, немного громоздко. Но мы можем написать программу преобразования для преобразования обычного HTML-кода вgo-app
Код, если интересно, можете реализовать сами. Технология WebAssembly очень достойна внимания~
Если вы найдете забавную и простую в использовании языковую библиотеку Go, вы можете отправить сообщение о проблеме в ежедневной библиотеке Go GitHub😄
Ссылаться на
- go-приложение GitHub:GitHub.com/Ma Shaun Test-Check…
- Перейти на ежедневный репозиторий GitHub:GitHub.com/Darenjun/go-of…
я
мой блог:darjun.github.io
Добро пожаловать, чтобы обратить внимание на мою общедоступную учетную запись WeChat [GoUpUp], учитесь вместе и добивайтесь прогресса вместе ~