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

  • 本文关键字:html 数据绑定 堆栈 管理 go
  • 更新时间 :
  • 英文 :


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

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

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

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 %sn", httpServer.Addr)
if err := httpServer.ListenAndServe(); err != nil {
log.Panic(err)
}
}

<html>
<head>
<title></title>
</head>
<body>
{{ yield }}
</body>
</html>

和共享视图

Hello, {{ .Name }}

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

警告:伪代码

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 %sn", httpServer.Addr)
if err := httpServer.ListenAndServe(); err != nil {
log.Panic(err)
}
}

允许我将这种布局更改为:

<html>
<head>
<title>{{ .Global.Title }}</title>
</head>
<body>
{{ .CurrentURL }}
{{ yield }}
</body>
</html>

并且事物被合并和绑定,而不需要单独的处理者进行太多思考。


希望你们有一些解决方案!我已经为此挣扎了一段时间。

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

https://github.com/valyala/quicktemplate

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

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

最新更新