【问题标题】:Creating load more button in Golang with templates使用模板在 Golang 中创建加载更多按钮
【发布时间】:2017-04-29 09:26:48
【问题描述】:

我想创建一个类似 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

感谢您的帮助。 :)

【问题讨论】:

  • 为什么要投反对票,如果您认为问题不好,请给予反馈。这对我来说是一个障碍,在这里寻找想法。
  • 我猜你投反对票是因为你很少研究或努力解决问题。另外,您的问题太宽泛了,但对于 web 应用程序来说,这是一个非常常见且方便的功能,所以无论如何我都会回答。

标签: ajax http templates go server


【解决方案1】:

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

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

在这里,我展示了一个可行的解决方案。这里的 Load more 按钮不会“记住”最后返回的帖子是什么,它只会检索 2 个新帖子。想一想如何实现发回最后一个 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" .}} 块,并且还为下一批(&lt;div id="nextBatch"&gt;)呈现一个占位符。接下来,它包含一个 Load More 按钮,当按下该按钮时,会以呈现的形式获取下一批,并替换占位符。渲染的下一批还包含下一批的占位符。

用于进行 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 Alice:正在下雨。
加载更多

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

帖子

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

再按一次:

帖子

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

【讨论】:

  • 它工作.. 谢谢。我不知道阻塞,不知何故我在你的上一篇文章中也错过了。这很棒。非常感谢您的帮助。
  • @DheerajSarwaiya 请注意,{{block}} 不是必需的,您可以在不使用 {{block}} 的情况下执行此操作。它只是 {{define}} 后跟 {{template}} 的简写。
  • 感谢您的帮助。我面临这种方法的一个问题。如果我使用块或模板,js 不起作用。我正在使用 js 脚本来显示来自从数据存储接收的 URL 的图像。我意识到即使是简单的 当您按加载更多时也不起作用。对此有何建议?
  • @DheerajSarwaiya 您尝试在模板中插入的文本很可能会被html/template 包自动转义。看看这个答案:Golang Web - HTML Comments are not rendered;还有这个:avoid auto escape in html template。如果这些没有帮助,我建议发布一个包含更多详细信息的新问题。
猜你喜欢
  • 2023-03-08
  • 2012-05-29
  • 2016-12-26
  • 2011-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-17
  • 1970-01-01
相关资源
最近更新 更多