操屁眼的视频在线免费看,日本在线综合一区二区,久久在线观看免费视频,欧美日韩精品久久综

新聞資訊

    題。windows10安裝Git報(bào)錯(cuò)unable to set system config "http.sslcainfo":="/ssl/certs/cabndle.crt":exit code128。

    是由于Win10系統(tǒng)沒(méi)有禁用驅(qū)動(dòng)程序強(qiáng)制簽名。

    禁用方式:win+r 打開運(yùn)行窗口,輸入

    gpedit.msc

    然后點(diǎn)擊【用戶設(shè)置】->【管理模板】->【系統(tǒng)】->【驅(qū)動(dòng)程序安裝】,在右側(cè)窗口點(diǎn)擊【設(shè)備驅(qū)動(dòng)程序的代碼簽名】->【策略設(shè)置】

    然后按照下圖修改

    以下文章來(lái)源于GoUpUp ,作者dj

    簡(jiǎn)介

    go-app是一個(gè)使用 Go + WebAssembly 技術(shù)編寫漸進(jìn)式 Web 應(yīng)用的庫(kù)。WebAssembly 是一種可以運(yùn)行在現(xiàn)代瀏覽器中的新式代碼。近兩年來(lái),WebAssembly 技術(shù)取得了較大的發(fā)展。我們現(xiàn)在已經(jīng)可以使用 C/C++/Rust/Go 等高級(jí)語(yǔ)言編寫 WebAssembly 代碼。本來(lái)就來(lái)介紹go-app這個(gè)可以方便地使用 Go 語(yǔ)言來(lái)編寫 WebAssembly 代碼的庫(kù)。

    快速使用

    go-app對(duì) Go 語(yǔ)言版本有較高的要求(Go 1.14+),而且必須使用Go module。先創(chuàng)建一個(gè)目錄并初始化Go Module(Win10 + Git Bash):

    $ mkdir go-app && cd go-app
    $ go mod init

    然后下載安裝go-app包:

    $ go get -u -v github.com/maxence-charriere/go-app/v6

    至于Go module的詳細(xì)使用,去看煎魚大佬的Go Modules 終極入門。

    首先,我們要編寫 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中使用組件來(lái)劃分功能模塊,每個(gè)組件結(jié)構(gòu)中必須內(nèi)嵌app.Compo。組件要實(shí)現(xiàn)Render()方法,在需要顯示該組件時(shí)會(huì)調(diào)用此方法返回顯示的頁(yè)面。go-app使用聲明式語(yǔ)法,完全使用 Go 就可以編寫 HTML 頁(yè)面,上面繪制 HTML 的部分比較好理解。上面代碼中還實(shí)現(xiàn)了一個(gè)輸入框的功能,并為它添加了一個(gè)監(jiān)聽(tīng)器。每當(dāng)輸入框內(nèi)容有修改,OnInputChange方法就會(huì)調(diào)用,g.Update()會(huì)使該組件重新渲染顯示。

    最后將該組件掛載到路徑/上。

    編寫 WebAssembly 程序之后,需要使用交叉編譯的方式將它編譯為.wasm文件:

    $ GOARCH=wasm GOOS=js go build -o app.wasm

    如果編譯出現(xiàn)錯(cuò)誤,使用go version命令檢查 Go 是否是 1.14 或更新的版本。

    接下來(lái),我們需要編寫一個(gè) Go Web 程序使用這個(gè)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提供了一個(gè)app.Handler結(jié)構(gòu),它會(huì)自動(dòng)查找同目錄下的app.wasm(這也是為什么將目標(biāo)文件設(shè)置為app.wasm的原因)。然后我們將前面編譯生成的app.wasm放到同一目錄下,執(zhí)行該程序:

    $ go run main.go

    默認(rèn)顯示"Hello World":

    在輸入框中輸入內(nèi)容之后,顯示會(huì)隨之變化:

    可以看到,go-app為我們?cè)O(shè)置了一些基本的樣式,網(wǎng)頁(yè)圖標(biāo)等。

    簡(jiǎn)單原理

    GitHub 上這張圖很好地說(shuō)明了 HTTP 請(qǐng)求的執(zhí)行流程:

    用戶請(qǐng)求先到app.Handler層,它會(huì)去app.wasm中執(zhí)行相關(guān)的路由邏輯、去磁盤上查找靜態(tài)文件。響應(yīng)經(jīng)由app.Handler中轉(zhuǎn)返回給用戶。用戶就看到了app.wasm渲染的頁(yè)面。實(shí)際上,在本文中我們只需要編寫一個(gè) Go Web 程序,每次編寫新的 WebAssembly 之后,將新編譯生成的 app.wasm 文件拷貝到 Go Web 目錄下重新運(yùn)行程序即可。注意,如果頁(yè)面未能及時(shí)刷新,可能是緩存導(dǎo)致的,可嘗試清理瀏覽器緩存

    組件

    自定義一個(gè)組件很簡(jiǎn)單,只需要將app.Compo內(nèi)嵌到結(jié)構(gòu)中即可。實(shí)現(xiàn)Render()方法可定義組件的外觀,實(shí)際上app.Compo有一個(gè)默認(rèn)的外觀,我們可以這樣來(lái)查看:

    func main() {
      app.Route("/app", &app.Compo{})
      app.Run()
    }

    編譯生成app.wasm之后,一開始的 Go Web 程序不需要修改,直接運(yùn)行,打開瀏覽器查看:

    事件處理

    快速開始中,我們還介紹了如何使用事件。使用聲明式語(yǔ)法app.Input().OnChange(handler)即可監(jiān)聽(tīng)內(nèi)容變化。事件處理函數(shù)必須為func (src app.Value, e app.Event)類型,app.Value是觸發(fā)對(duì)象,app.Event是事件的內(nèi)容。通過(guò)app.Value我們可以得到輸入框內(nèi)容、選擇框的選項(xiàng)等信息,通過(guò)app.Event可以得到事件的信息,是鼠標(biāo)事件、鍵盤事件還是其它事件:

    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()
    }

    上面代碼顯示一個(gè)選擇框,當(dāng)選項(xiàng)改變時(shí)上面顯示的文字會(huì)做相應(yīng)的改變。初始時(shí):

    選擇后:

    嵌套組件

    組件可以嵌套使用,即在一個(gè)組件中使用另一個(gè)組件。渲染時(shí)將內(nèi)部的組件表現(xiàn)為外部組件的一部分:

    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中內(nèi)嵌了一個(gè)Name組件,運(yùn)行顯示:

    生命周期

    go-app提供了組件的 3 個(gè)生命周期的鉤子函數(shù):

    • OnMount:當(dāng)組件插入到 DOM 時(shí)調(diào)用;
    • OnNav:當(dāng)一個(gè)組件所在頁(yè)面被加載、刷新時(shí)調(diào)用;
    • OnDismount:當(dāng)一個(gè)組件從頁(yè)面中移除時(shí)調(diào)用。

    例如:

    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()
    }

    編譯運(yùn)行,在瀏覽器中打開頁(yè)面,打開瀏覽器控制臺(tái)觀察輸出:

    component mounted
    component navigated: http://localhost:8080/

    編寫 HTML

    在前面的例子中我們已經(jīng)看到了如何使用聲明式語(yǔ)法編寫 HTML 頁(yè)面。go-app為所有標(biāo)準(zhǔn)的 HTML 元素都提供了相關(guān)的類型。創(chuàng)建這些對(duì)象的方法名也比較好記,就是元素名的首字母大寫。如app.Div()創(chuàng)建一個(gè)div元素,app.P()創(chuàng)建一個(gè)p元素,app.H1()創(chuàng)建一個(gè)h1元素等等。在go-app中,這些結(jié)構(gòu)都是暴露出對(duì)應(yīng)的接口供開發(fā)者使用的,如div對(duì)應(yīng)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
    }

    可以看到每個(gè)方法都返回該HTMLDiv自身,所以支持鏈?zhǔn)秸{(diào)用。調(diào)用這些方法可以設(shè)置元素的各方面屬性:

    • Class:添加 CSS Class;
    • ID:設(shè)置 ID 屬性;
    • Style:設(shè)置內(nèi)置樣式;
    • Body:設(shè)置元素內(nèi)容,可以隨意嵌套。div中包含h1和p,p中包含img等;

    和設(shè)置事件監(jiān)聽(tīng):

    • OnClick:點(diǎn)擊事件;
    • OnKeyPress:按鍵事件;
    • OnMouseOver:鼠標(biāo)移過(guò)事件。

    例如下面代碼:

    app.Div().Body(
      app.H1().Body(
        app.Text("Title"),
      ),
      app.P().ID("id").
        Class("content").Body(
          app.Text("something interesting"),
        ),
    )

    相當(dāng)于 HTML 代碼:

    <div>
      <h1>title</h1>
      <p id="id" class="content">
        something interesting
      </p>
    </div>

    原生元素

    我們可以在app.Raw()中直接寫 HTML 代碼,app.Raw()會(huì)生成對(duì)應(yīng)的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>
    `)

    但是這種寫法是不安全的,因?yàn)闆](méi)有檢查 HTML 的結(jié)構(gòu)。

    條件

    我們?cè)谧铋_始的例子中就已經(jīng)用到了條件語(yǔ)句,條件語(yǔ)句對(duì)應(yīng) 3 個(gè)方法:If()/ElseIf()/Else()。

    If和ElseIf接收兩個(gè)參數(shù),第一個(gè)參數(shù)為bool值。如果為true,則顯示第二個(gè)參數(shù)(類型為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()
    }

    上面我們根據(jù)輸入的分?jǐn)?shù)顯示對(duì)應(yīng)的文字,90及以上顯示綠色的Good!,60-90之間顯示橙色的Pass!,小于60顯示紅色的Fail!。下面是運(yùn)行結(jié)果:

    Range

    假設(shè)我們要編寫一個(gè) HTML 列表,當(dāng)前有一個(gè)字符串的切片。如果一個(gè)個(gè)寫就太繁瑣了,而且不夠靈活,且容易出錯(cuò)。這時(shí)就可以使用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()可以對(duì)切片或map中每一項(xiàng)生成一個(gè)app.UI,然后平鋪在某個(gè)元素的Body()方法中。

    運(yùn)行結(jié)果:

    上下文菜單

    在go-app中,我們可以很方便的自定義右鍵彈出的菜單,并且為菜單項(xiàng)編寫響應(yīng):

    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()
    }

    我們?cè)贠nContextMenu中調(diào)用了event.PreventDefault()阻止默認(rèn)菜單的彈出??催\(yùn)行結(jié)果:

    點(diǎn)擊菜單項(xiàng),觀察控制臺(tái)輸出~

    app.Handler

    上面我們都是使用go-app內(nèi)置的app.Handler處理客戶端的請(qǐng)求。我們只設(shè)置了簡(jiǎn)單的兩個(gè)屬性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:設(shè)置應(yīng)用圖標(biāo);
    • Styles:CSS 樣式文件;
    • Scripts:JS 腳本文件。

    CSS 和 JS 文件必須在app.Handler中聲明。下面是一個(gè)示例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 演示代碼在 web 目錄中。先進(jìn)入某個(gè)目錄,使用下面的命令編譯:

    $ GOARCH=wasm GOOS=js go build -o app.wasm

    然后將生成的app.wasm拷貝到web目錄:

    $ cp app.wasm ../web/

    切換到 web 目錄,啟動(dòng)服務(wù)器:

    $ cd ../web/
    $ go run main.go

    總結(jié)

    本文介紹如何使用go-app編寫基于 WebAssembly 的 Web 應(yīng)用程序。可能有人會(huì)覺(jué)得,go-app編寫 HTML 的方式有點(diǎn)繁瑣。但是我們可以寫一個(gè)轉(zhuǎn)換程序?qū)⑵胀ǖ?HTML 代碼轉(zhuǎn)為go-app代碼,感興趣可以自己實(shí)現(xiàn)一下。WebAssembly 技術(shù)非常值得關(guān)注一波~

網(wǎng)站首頁(yè)   |    關(guān)于我們   |    公司新聞   |    產(chǎn)品方案   |    用戶案例   |    售后服務(wù)   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區(qū)    電話:010-     郵箱:@126.com

備案號(hào):冀ICP備2024067069號(hào)-3 北京科技有限公司版權(quán)所有