第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何使用 golang html/template 的基本模板文件?

如何使用 golang html/template 的基本模板文件?

Go
達令說 2022-01-04 13:39:04
擁有 gin-gonic 網(wǎng)絡應用程序。有3個文件:1) base.html -- 基本布局文件<!DOCTYPE html><html><body>header...{{template "content" .}}footer...</body></html>2) page1.html,為/page1{{define "content"}}<div>    <h1>Page1</h1></div>{{end}}{{template "base.html"}}3) page2.html,用于/page2{{define "content"}}<div>    <h1>Page2</h1></div>{{end}}{{template "base.html"}}問題是 /page1 和 /page2 使用一個模板 - page2.html。我認為我對這樣的結構有誤解:{{define "content"}}, {{template "base.html"}}.拜托,你能舉例說明如何在 golang 中使用基本布局嗎?
查看完整描述

3 回答

?
慕桂英546537

TA貢獻1848條經(jīng)驗 獲得超10個贊

只要您將模板與“內(nèi)容”一起解析,您就可以使用 base.html,如下所示:


基本文件


{{define "base"}}

<!DOCTYPE html>

<html>

<body>


header...


{{template "content" .}}


footer...


</body>

</html>

{{end}}

頁面1.html


{{define "content"}}

I'm page 1

{{end}}

頁面2.html


{{define "content"}}

I'm page 2

{{end}}

然后ParseFiles with ("your-page.html", "base.html") 和ExecuteTemplate與你的上下文。


tmpl, err := template.New("").ParseFiles("page1.html", "base.html")

// check your err

err = tmpl.ExecuteTemplate(w, "base", yourContext)


查看完整回答
反對 回復 2022-01-04
?
慕蓋茨4494581

TA貢獻1850條經(jīng)驗 獲得超11個贊

Go 1.16 引入了 embed 包,將非 .go 文件打包成二進制文件,極大地方便了 Go 程序的部署。該ParseFS函數(shù)還添加到標準庫 html/template 中,它將 embed.FS 中包含的所有模板文件編譯為模板樹。


// templates.go

package templates


import (

    "embed"

    "html/template"

)


//go:embed views/*.html

var tmplFS embed.FS


type Template struct {

    templates *template.Template

}


func New() *Template {

    funcMap := template.FuncMap{

        "inc": inc,

    }


    templates := template.Must(template.New("").Funcs(funcMap).ParseFS(tmplFS, "views/*.html"))

    return &Template{

        templates: templates,

    }

}



// main.go

t := templates.New()

t.templates是一個全局模板,包含所有匹配的views/*.html模板,所有模板都是相關的,可以相互引用,模板的名字就是文件的名字,例如article.html.


此外,我們Render為該*Template類型定義了一個方法,該方法實現(xiàn)Renderer了 Echo Web 框架的接口。


// templates.go

func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {

    return t.templates.ExecuteTemplate(w, name, data)

}

然后,您可以為 Echo 指定渲染器,以便在每個處理程序中生成 HTML 響應,只需將模板的名稱傳遞給c.Render函數(shù)即可。


// main.go

func main() {

    t := templates.New()


    e := echo.New()

    e.Renderer = t

}



// handler.go

func (h *Handler) articlePage(c echo.Context) error {

    id := c.Param("id")

    article, err := h.service.GetArticle(c.Request().Context(), id)

    ...

    return c.Render(http.StatusOK, "article.html", article)

}

由于t.templates模板包含了所有解析的模板,每個模板名稱都可以直接使用。


為了組裝 HTML,我們需要使用模板繼承。例如,為基本的 HTML 框架和<head>元素定義一個 layout.html ,并設置{{block "title"}}和{{block "content"}},其他模板繼承 layout.html,并使用自己定義的塊填充或覆蓋布局模板的同名塊。


以下是layout.html模板的內(nèi)容。


<!DOCTYPE html>

<html>


<head>

    <meta charset="UTF-8">

    <meta http-equiv="X-UA-Compatible" content="IE=edge">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>{{block "title" .}}{{end}}</title>

    <script src="/static/main.js"></script>

</head>


<body>

    <div class="main">{{block "content" .}}{{end}}</div>

</body>


</html>

其他模板可以參考(繼承)layout.html,在layout.html模板中定義blocks。


例如,login.html 內(nèi)容如下。


{{template "layout.html" .}}


{{define "title"}}Login{{end}}


{{define "content"}}

<form class="account-form" method="post" action="/account/login" data-controller="login">

    <div div="account-form-title">Login</div>

    <input type="phone" name="phone" maxlength="13" class="account-form-input" placeholder="Phone" tabindex="1">

    <div class="account-form-field-submit ">

        <button type="submit" class="btn btn-phone">Login</button>

    </div>

</form>

{{end}}

article.html 還引用了 layout.html:


{{template "layout.html" .}}


{{define "title"}}<h1>{{.Title}}</h1>{{end}}


{{define "content"}}

<p>{{.URL}}</p>

<article>{{.Content}}</article>

{{end}}

我們希望 login.html 模板中定義的塊在渲染時覆蓋 layout.html 中的塊,也在渲染 article.html 模板時覆蓋。但事實并非如此,這取決于 Go 文本/模板實現(xiàn)。在我們的實現(xiàn)中ParseFS(tmplFS, "views/*.html"),假設先解析article.html并將其content塊解析為模板名稱,那么當稍后解析login.html模板并content在其中找到一個塊時,text/template將覆蓋該模板的模板與后面解析的內(nèi)容同名,所以當所有的模板都解析完后,content我們的模板樹中實際上只有一個模板命名,也就是content上次解析的模板文件中定義的。


因此,當我們執(zhí)行article.html模板時,有可能該content模板不是本模板中定義的內(nèi)容,而是content其他模板中定義的內(nèi)容。


社區(qū)針對這個問題提出了一些解決方案。例如,不是使用全局模板,而是在每次渲染時創(chuàng)建一個新模板,僅包含 layout.html 和子模板的內(nèi)容。但這真的很乏味。事實上,當 Go 1.6block為文本/模板引入指令 [1] 時,我們能夠使用該Clone方法做我們想做的事情,只需對上面的代碼進行一些更改。


// templates.go

package templates


import (

    "embed"

    "html/template"

    "io"


    "github.com/labstack/echo/v4"

)


//go:embed views/*.html

var tmplFS embed.FS


type Template struct {

    templates *template.Template

}


func New() *Template {

    funcMap := template.FuncMap{

        "inc": inc,

    }


    templates := template.Must(template.New("").Funcs(funcMap).ParseFS(tmplFS, "views/*.html"))

    return &Template{

        templates: templates,

    }

}


func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {

    tmpl := template.Must(t.templates.Clone())

    tmpl = template.Must(tmpl.ParseFS(tmplFS, "views/"+name))

    return tmpl.ExecuteTemplate(w, name, data)

}

可以看到Render這里只修改了函數(shù)。我們不會執(zhí)行全局模板,而是將其克隆到一個新模板中,而content這個新模板中的塊可能不是我們想要的,所以這里我們解析一個子模板的內(nèi)容,我們最終將在此之上渲染全局模板,這樣content新添加的子模板的 將覆蓋以前的,可能不正確的content。我們的目標子模板引用了全局模板中的layout.html,這并不沖突,而且由于全局模板從來沒有被執(zhí)行過(Render每次執(zhí)行我們在函數(shù)中克隆一個新的全局模板),它也是干凈的。當一個模板最終被執(zhí)行時,我們有一個干凈的 layout.htmlcontent我們想要的內(nèi)容,相當于每次執(zhí)行都會生成一個新的模板,里面只包含我們需要的布局模板和子模板。思路是一樣的,只不過不是在執(zhí)行模板時手動生成新模板,而是在Render函數(shù)中自動完成。


當然,也可以使用{{ template }}來引用子模板中的其他布局模板,只要這些布局模板不相互覆蓋,執(zhí)行時只需要指定目標子模板的名稱,模板引擎會自動使用其中{{ template }}定義的標簽為我們尋找布局模板,這些模板都在克隆的全局模板中。


[1] https://github.com/golang/go/commit/12dfc3bee482f16263ce4673a0cce399127e2a0d


查看完整回答
反對 回復 2022-01-04
?
四季花海

TA貢獻1811條經(jīng)驗 獲得超5個贊

據(jù)我了解,當您使用 時ParseGlob(),Gin 會解析所有匹配的文件并從中創(chuàng)建一個模板對象。為了做你想做的事,你需要兩個不同的模板(一個用于第 1 頁,另一個用于第 2 頁)。


Gin 文檔說這是一個已知的限制,并指出了克服它的方法:


Gin 默認只允許使用一個 html.Template。檢查多模板渲染以使用 go 1.6 等功能block template。


使用多模板庫,您可以編寫如下內(nèi)容:


    render := multitemplate.NewRenderer()


    render.AddFromFiles("page1", "templates/base.html", "templates/page1.html")

    render.AddFromFiles("page2", "templates/base.html", "templates/page2.html")


    router := gin.Default()

    router.HTMLRender = render


    // Later

    ginContext.HTML(200, "page1", gin.H{

            "title": "The Wonderful Page One",

        })

這需要比我希望的更多的手動設置,但可以完成工作。


查看完整回答
反對 回復 2022-01-04
  • 3 回答
  • 0 關注
  • 332 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網(wǎng)微信公眾號