使用模板在Golang中创建load more按钮

时间:2016-12-14 06:17:05

标签: ajax http templates go server

我想创建一个类似Facebook的页面,如果用户向下滚动页面获取旧帖子而不刷新。我之前使用Ajax并使用JS附加HTML页面。

但是,由于我现在使用Go及其模板来构建页面,我不知道如何实现类似的结果。请帮助我提出你的建议。

{{range .posts}}
 <<in side the range brackets, I am showing the posts >>
{{end}}
out side range I have created load more button which calls 
the js which internally fetch the posts slice.

下面的链接显示了一个解决方案,但它不适用于大量数据,在js中创建所有这些按钮将很困难。 Dynamically refresh a part of the template when a variable is updated golang

感谢您的帮助。 :)

1 个答案:

答案 0 :(得分:5)

我在您的问题中链接的其他答案包含了实施“加载更多...”功能所需的所有详细信息和技巧:Dynamically refresh a part of the template when a variable is updated golang

是的,这不是微不足道的,但它也不是那么难/复杂。该答案讨论了不同的方式/替代方案,但显然解决方案只需要一个。

这里我展示了一个有效的解决方案。这里的加载更多按钮不会“记住”返回的最后一个帖子,它只会检索2个新帖子。考虑一下如何实现发回最后一个ID,并在请求更多ID时,发送跟踪后的记录。

可以在Go Playground上找到完整的,可运行的应用程序代码。当然,您无法在Go Playground上运行它,在本地保存并在您的计算机上运行它。

因此,我们将使用以下Post个实体:

type Post struct {
    User, Time, Text string
}

我将使用以下模板:

<html><body><h2>Posts</h2>
{{block "batch" .}}
    {{range .posts}}
        <div><b>{{.Time}} {{.User}}:</b> {{.Text}}</div>
    {{end}}
    <div id="nextBatch"></div>
{{end}}
<button onclick="loadMore()">Load more</button>
<script>
    function loadMore() {
        var e = document.getElementById("nextBatch");
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function() {
            if (xhr.readyState == 4 && xhr.status == 200) {
                e.outerHTML = xhr.responseText;
            }
        }
        xhr.open("GET", "/posts/more", true);
        try { xhr.send(); } catch (err) { /* handle error */ }
    }
</script>
</body></html>

它包含用于列出帖子的{{block "batch" .}}块,还为下一批(<div id="nextBatch">)呈现占位符。接下来它包含一个加载更多按钮,按下该按钮后,以渲染形式获取下一批,并替换占位符。渲染的下一批次还包含下一批次的占位符。

用于进行AJAX调用的javascript函数在我链接的另一个答案中有详细说明。

执行此模板的处理程序:

var t = template.Must(template.New("").Parse(page))

var lastTime = time.Now()

func produceTime() string {
    lastTime = lastTime.Add(time.Second)
    return lastTime.Format("15:04:05")
}

func postsHandler(w http.ResponseWriter, r *http.Request) {
    // Put up some random data for demonstration:
    data := map[string]interface{}{"posts": []Post{
        {User: "Bob", Time: produceTime(), Text: "The weather is nice."},
        {User: "Alice", Time: produceTime(), Text: "It's raining."},
    }}
    var err error
    switch r.URL.Path {
    case "/posts/":
        err = t.Execute(w, data)
    case "/posts/more":
        err = t.ExecuteTemplate(w, "batch", data)
    }
    if err != nil {
        log.Printf("Template execution error: %v", err)
    }
}

produceTime()只会产生单调递增的时间戳字符串,因此输出看起来像是明智的。

注册处理程序并启动服务器的main()函数:

func main() {
    http.HandleFunc("/posts/", postsHandler)
    panic(http.ListenAndServe(":8080", nil))
}

就是这样。这是一个有效的应用程序。在浏览器中输入http://localhost:8080/posts/,您会看到:

  

帖子

     

09:42:29 Bob:天气很好    09:42:30爱丽丝:正在下雨   加载更多

加载更多按钮,浏览器中的内容将动态刷新,无需重新加载页面。新内容:

  

帖子

     

09:42:29 Bob:天气很好    09:42:30爱丽丝:正在下雨    09:42:31 Bob:天气很好    09:42:32爱丽丝:正在下雨   加载更多

再次按下:

  

帖子

     

09:42:29 Bob:天气很好    09:42:30爱丽丝:正在下雨    09:42:31 Bob:天气很好    09:42:32爱丽丝:正在下雨    09:42:33 Bob:天气很好    09:42:34爱丽丝:正在下雨   加载更多