使用Golang模板实现可复用的Web UI组件

使用Golang模板实现可复用的Web UI组件 大家好,

我在想是否可以使用 Go 模板来构建通用的、可复用的 Web UI 组件,例如树形组件(使用 Go HTML 模板),这些组件之后可以在整个项目中使用。有人尝试过吗?

2 回复

k-p-ani:

有人试过吗?

类似这样的东西?你的想象力就是你的极限……

更多关于使用Golang模板实现可复用的Web UI组件的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


是的,完全可以使用Go模板构建可复用的Web UI组件。Go模板的definetemplate动作非常适合创建组件化架构。下面是一个树形组件的实现示例:

1. 基础组件模板 (components.tmpl):

{{/* 树节点组件 */}}
{{define "treeNode"}}
<li class="tree-node">
    <div class="node-content">
        {{if .Children}}
            <span class="toggle">▶</span>
        {{end}}
        <span class="label">{{.Label}}</span>
    </div>
    {{if .Children}}
        <ul class="tree-children" style="display: none;">
            {{range .Children}}
                {{template "treeNode" .}}
            {{end}}
        </ul>
    {{end}}
</li>
{{end}}

{{/* 树容器组件 */}}
{{define "tree"}}
<div class="tree-container" id="{{.ID}}">
    <ul class="tree-root">
        {{range .Nodes}}
            {{template "treeNode" .}}
        {{end}}
    </ul>
</div>
<script>
    document.getElementById('{{.ID}}').addEventListener('click', function(e) {
        if (e.target.classList.contains('toggle')) {
            const children = e.target.closest('.tree-node').querySelector('.tree-children');
            children.style.display = children.style.display === 'none' ? 'block' : 'none';
            e.target.textContent = e.target.textContent === '▶' ? '▼' : '▶';
        }
    });
</script>
{{end}}

2. 数据模型 (models.go):

type TreeNode struct {
    ID       string
    Label    string
    Children []TreeNode
}

type TreeData struct {
    ID    string
    Nodes []TreeNode
}

3. 使用组件的页面模板 (page.tmpl):

<!DOCTYPE html>
<html>
<head>
    <title>Tree Component Example</title>
    <style>
        .tree-container { font-family: Arial; }
        .tree-node { list-style: none; margin: 5px 0; }
        .node-content { cursor: pointer; padding: 3px; }
        .toggle { margin-right: 5px; display: inline-block; }
        .tree-children { padding-left: 20px; }
    </style>
</head>
<body>
    <h1>文件浏览器</h1>
    
    {{/* 使用树组件 */}}
    {{template "tree" .FileTree}}
    
    <h1>菜单导航</h1>
    
    {{/* 复用同一个树组件 */}}
    {{template "tree" .MenuTree}}
</body>
</html>

4. Go代码实现 (main.go):

package main

import (
    "html/template"
    "net/http"
)

func main() {
    tmpl := template.Must(template.ParseFiles(
        "components.tmpl",
        "page.tmpl",
    ))

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        data := map[string]interface{}{
            "FileTree": TreeData{
                ID: "fileTree",
                Nodes: []TreeNode{
                    {
                        Label: "src",
                        Children: []TreeNode{
                            {Label: "main.go"},
                            {Label: "utils.go"},
                        },
                    },
                    {Label: "README.md"},
                },
            },
            "MenuTree": TreeData{
                ID: "menuTree",
                Nodes: []TreeNode{
                    {
                        Label: "设置",
                        Children: []TreeNode{
                            {Label: "用户管理"},
                            {Label: "系统配置"},
                        },
                    },
                },
            },
        }
        
        tmpl.ExecuteTemplate(w, "page", data)
    })

    http.ListenAndServe(":8080", nil)
}

5. 带参数的组件示例 (可配置的按钮组件):

{{/* 可配置的按钮组件 */}}
{{define "button"}}
<button 
    class="btn {{.Class}}"
    type="{{.Type}}"
    {{if .ID}}id="{{.ID}}"{{end}}
    {{if .OnClick}}onclick="{{.OnClick}}"{{end}}>
    {{if .Icon}}<i class="{{.Icon}}"></i>{{end}}
    {{.Text}}
</button>
{{end}}

{{/* 使用示例 */}}
{{template "button" dict "Text" "提交" "Class" "btn-primary" "Type" "submit"}}
{{template "button" dict "Text" "删除" "Class" "btn-danger" "OnClick" "confirmDelete()"}}

这个实现展示了如何通过Go模板的define定义组件、template调用组件,以及如何传递结构化数据给组件。树形组件包含了完整的HTML结构、CSS样式和JavaScript交互逻辑,可以在项目的任何地方复用。

回到顶部