【问题标题】:Golang Template Range (for loop) using JSON from WebSocket使用来自 WebSocket 的 JSON 的 Golang 模板范围(for 循环)
【发布时间】:2017-07-07 15:13:30
【问题描述】:

我正在使用 Gorilla Websocket 来更新一些 HTML(img src、文本等);我这样做的方式如下:

mt, message, err := c.ReadMessage()
if err != nil {
    log.Println("read:", err)
    break
}
[...]
app, err := models.DB.SearchAppStore(ctx, stars, updatedWithin, 0)
myJson, err := json.Marshal(app)
err = c.WriteMessage(mt, myJson)
if err != nil {
    log.Println("write:", err)
    break
}

然后我使用 javascript 以这种方式更新 HTML 数据:

ws.onmessage = function(evt) {
    var d = JSON.parse(evt.data);
    var app;
    for (app = 0; app < 3; app++) {
      document.getElementById("app-icon-" + app).src = d[app].ThumbnailURL;
      document.getElementById("app-title-" + app).innerHTML = d[app].Title;
      document.getElementById("app-compatibility-" + app).innerHTML = d[app].Compatibility;
    }
  };

然后我以这种方式手动输入了 HTML:

<div class="app-section">
  <div class="icon">
    <img src="" id="app-icon-0">
  </div>
  <div class="details">
    <h2 id="app-title-0"></h2>
    <h5 id="app-compatibility-0"></h5>
  </div>
</div>

您可以在 HTML 'id's 中看到 0,我应该注意它要长得多,但我试图只取相关部分..

我当然不想手动输入 HTML,因为它会使处理不同的长度变得困难(/不可能)(比如有时我想显示一百个应用程序,有时可能只有 3 个可用,等等..)

我在想这也许可以使用 golang 的 HTML {{range}} 函数来完成,但我不知道如何将它与来自 websockets 的 json 数据集成..

另一个应该可以管理的解决方案是在ws.onmessage 处写出 JS for 循环中的所有 HTML,但我认为如果我学会如何使用 golang 模板包来做到这一点会更好。尤其是因为它真的很长,而且有很多类/ID..

在我看来,我需要获取 JSON (Object.keys(d).length;) 的长度,然后我需要在 {{range}} 内传递这个长度,然后可以使用 {{index}} 进行交互JSON 对象..

..但我无法弄清楚如何做到这一点,也许这甚至不可能..我将不胜感激任何关于如何做到这一点的帮助..

【问题讨论】:

  • 这似乎是你应该在 JavaScript 中做的事情。您可以使用document.createElement() 动态创建新元素。从代码动态创建 DOM 是如此普遍,以至于为此目的存在一个框架 ReactJS。
  • 嗯,我也在研究 document.createElement/jquery 解决方案,因为我不知道如何使用 golang 模板包来完成它,只是觉得它是一团糟。我也一直在为是否将 ReactJS 集成到项目中而苦苦挣扎,因为我担心学习起来会太费时.. 但我想这是值得的.. 谢谢

标签: javascript html go websocket go-html-template


【解决方案1】:

一种简单的方法是在服务器上执行一个模板,然后将生成的 HTML 发送到将 HTML 插入页面的客户端。

使用已编译的模板声明包级变量。 此模板假定 Execute 的参数是 具有 ThumbnailURL、Title 和 Compatibility 字段的结构或映射。

var t = template.Must(template.New("").Parse(`{{range .}}
  <div class="icon">
   <img src="{{.ThumbnailURL}}">
  </div>
  <div class="details">
   <h2>{{.Title}}</h2>
   <h5>{{.Compatibility}}</h5>
  </div>{{end}}`))

在读取循环中执行模板。将 HTML 发送给客户端:

mt, message, err := c.ReadMessage()
if err != nil {
   log.Println("read:", err)
   break
]
[...]
app, err := models.DB.SearchAppStore(ctx, stars, updatedWithin, 0)
var buf bytes.Buffer
if err := t.Execute(&buf, app); err != nil {
    // handle error
}
err = c.WriteMessage(mt, buf.Bytes())
if err != nil {
  log.Println("write:", err)
  break
}

为页面上的结果添加一个 div:

<div class="app-section"></div>

在收到消息时设置 div 的内部 HTML:

ws.onmessage = function(evt) {
    document.getElementById("app-section").innerHTML = evt.Data;
}

此解决方案不使用 JSON。

【讨论】:

  • 哇,太棒了,这正是我希望的,而不是使用 jquery/document.createElement 来实现。非常感谢!!
猜你喜欢
  • 2021-09-14
  • 1970-01-01
  • 2021-05-02
  • 2016-11-06
  • 2017-05-22
  • 1970-01-01
  • 1970-01-01
  • 2010-10-30
  • 2021-01-24
相关资源
最近更新 更多