首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通过堆栈管理和提供html/模板数据绑定

通过堆栈管理和提供html/模板数据绑定
EN

Stack Overflow用户
提问于 2019-01-10 18:10:30
回答 1查看 299关注 0票数 0

是否有人在使用Go的html/template时实现了管理视图绑定的解决方案?具体来说,我希望找到一些能让我做以下事情的东西:

  • 在安装Site.Title期间设置全局
  • 提供请求范围内的变量,如CurrentURL
  • 然后,在Render步骤中,只需提供http.Handler-specific变量,然后将其组合并提供给模板。

现有应用程序的示例如下(我使用unrolled/render进行布局继承,但这是可替换的):

代码语言:javascript
复制
package main

import (
    "log"
    "net"
    "net/http"
    "os"
    "strings"

    "github.com/go-chi/chi"
    "github.com/go-chi/chi/middleware"
    "github.com/unrolled/render"
)

type HelloBinding struct {
    Name string
}

func helloHandler(render *render.Render) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        _ = render.HTML(w, http.StatusOK, "hello", &HelloBinding{
            Name: "World!",
        })
    }
}

func main() {
    port, ok := os.LookupEnv("PORT")
    if !ok {
        port = "8080"
    }

    render := render.New(render.Options{
        Directory:     "templates",
        Layout:        "layout",
        Extensions:    []string{".html"},
        IsDevelopment: true,
    })

    r := chi.NewMux()

    r.Use(middleware.Logger)
    r.Use(middleware.Recoverer)

    r.Get("/", helloHandler(render))

    httpServer := &http.Server{
        Addr:    net.JoinHostPort("", port),
        Handler: r,
    }

    log.Printf("http server listening at %s\n", httpServer.Addr)
    if err := httpServer.ListenAndServe(); err != nil {
        log.Panic(err)
    }
}

代码语言:javascript
复制
<html>
<head>
    <title></title>
</head>
<body>

    {{ yield }}

</body>
</html>

和一个共同的观点

代码语言:javascript
复制
Hello, {{ .Name }}

在一个理想的解决方案中,这样的事情是可能的:

警告:伪代码

代码语言:javascript
复制
package main

import (
    "log"
    "net"
    "net/http"
    "os"
    "strings"

    "github.com/go-chi/chi"
    "github.com/go-chi/chi/middleware"
    "github.com/unrolled/render"
)

type GlobalBinding struct {
    Title string
}

type RequestBinding struct {
    CurrentURL string
}

type HelloBinding struct {
    Name string
}

func helloHandler(render *render.Render) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        _ = render.HTML(w, http.StatusOK, "hello", &HelloBinding{
            Name: "World!",
        })
    }
}

func main() {
    port, ok := os.LookupEnv("PORT")
    if !ok {
        port = "8080"
    }

    render := render.New(render.Options{
        Directory:     "templates",
        Layout:        "layout",
        Extensions:    []string{".html"},
        IsDevelopment: true,
    })

    // Binds data to be used
    render.Bind(GlobalBindings{
        Title: "My Site",
    })

    r := chi.NewMux()

    r.Use(middleware.Logger)
    r.Use(middleware.Recoverer)

    // Binds data for the request context only
    r.Use(func(next http.Handler) http.Handler {
        return func(w http.ResponseWriter, r *http.Request) {
            render.BindContext(r.Context, RequestBinding{
                CurrentURL: r.URL.String(),
            })
            next(w, r)
        }
    })

    r.Get("/", helloHandler(render))

    httpServer := &http.Server{
        Addr:    net.JoinHostPort("", port),
        Handler: r,
    }

    log.Printf("http server listening at %s\n", httpServer.Addr)
    if err := httpServer.ListenAndServe(); err != nil {
        log.Panic(err)
    }
}

允许我将类似的布局更改为:

代码语言:javascript
复制
<html>
<head>
    <title>{{ .Global.Title }}</title>
</head>
<body>

    {{ .CurrentURL }}

    {{ yield }}

</body>
</html>

事物被合并和绑定,而没有经过个别处理者的太多思考。

希望你们有解决办法!我在这件事上挣扎了一段时间。

EN

回答 1

Stack Overflow用户

发布于 2019-01-11 01:18:44

不是在html/template中,而是考虑使用快速模板

https://github.com/valyala/quicktemplate

它是围绕常规代码设计的,因此您的呈现器只是可以接受任意参数(和接口)的函数。您可以导入包,调用常规函数并访问全局变量。

与内置模板引擎相比,使用它要舒服得多,而且您还可以进行静态类型检查。唯一的缺点是编辑后需要重新构建/重新启动以反映更改。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54134591

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档