【问题标题】:Knockout JS, live updating data from websocketKnockout JS,从 websocket 实时更新数据
【发布时间】:2023-03-16 20:43:01
【问题描述】:

我正在尝试从 websocket 加载数据以使用敲除和 gaugeMeter.js 在仪表上显示。 我不断收到“无法将绑定多次应用于同一元素”错误。 这是代码 HTML

<div class="GaugeMeter gaugeMeter" id="PreviewGaugeMeter" data-bind="gaugeValue: Percent" data-size=350 data-theme="Orange" data-back="Grey"
  data-text_size="0.4" data-width=38 data-style="Arch" data-animationstep="0" data-stripe="3"></div>

JS

// Bind new handler to init and update gauges.
      ko.bindingHandlers.gaugeValue = {
        init: function(element, valueAccessor) {
            $(element).gaugeMeter({ percent: ko.unwrap(valueAccessor()) });
        },
        update: function(element, valueAccessor) {
          
            $(element).gaugeMeter({ percent: activePlayerData.boost });
            
        }
      };

      // Create view model with inital gauge value 15mph
      // Use observable for easy update.
      var myViewModel = {
        Percent: ko.observable(15)
      };
      
      ko.applyBindings(myViewModel);

activePlayerData.boost 是我从 websocket 获取的数据,需要更新值,它总是显示第一个值,但之后的所有内容都会出现错误。 我真的很迷茫,因为我对编码很陌生。

【问题讨论】:

  • 你需要展示当 websocket 消息到达时会发生什么。

标签: javascript knockout.js


【解决方案1】:

下面是适用于您的用例的最小工作示例。你可以运行它来看看它做了什么:

// simple gaugeMeter jQuery plugin mockup
$.fn.gaugeMeter = function (params) {
  return this.css({width: params.percent + '%'}).text(params.percent);
}

// binding handler for that plugin
ko.bindingHandlers.gaugeValue = {
  update: function(element, valueAccessor) {
    var boundValue = valueAccessor();
    var val = ko.unwrap(boundValue); // or: val = boundValue();
    $(element).gaugeMeter({ percent: val });
  }
};

// set up viewmodel
var myViewModel = {
  Percent: ko.observable(15)
};
ko.applyBindings(myViewModel);
  
// simulate regular value updates
setInterval(function () {
  var newPercentValue = Math.ceil(Math.random() * 100);
  myViewModel.Percent(newPercentValue);
}, 1500);
div.gaugeMeter {
  background-color: green;
  height: 1em;
  color: white;
  padding: 3px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="gaugeMeter" data-bind="gaugeValue: Percent"></div>

要理解的事情:

  • 每当绑定的可观察对象(即Percent)更改其值时,就会调用绑定处理程序的update 部分。如果没有要初始化的内容,您并不严格需要 init 部分。

  • valueAccessor 为您提供了包含绑定值的东西。通常,但不一定这是一个可观察的 - 就像你的情况一样。一旦你调用了valueAccessor(),你仍然需要打开(也就是“unwrap”)那个 observable 来看看里面有什么。这就是为什么我上面的代码需要两个步骤,valueAccessor()ko.unwrap()

    • 什么时候它不是可观察的? - 当视图模型具有{basicEfficiency: 15}。在所有情况下,valueAccessor() 都会为您提供那个值,无论是否可观察。
    • 为什么使用ko.unwrap(boundValue) 而不是boundValue() - 前者适用于文字值和可观察对象,后者仅适用于可观察对象。在绑定处理程序中,支持这两种用例是有意义的。
  • 一旦更新到达,例如通过 WebSocket,不要尝试重新应用任何绑定或重新初始化任何内容。

    您需要做的就是更改视图模型中相应可观察对象的值。通过调用来更改 observable 的值:myViewModel.Percent(15); 会将 myViewModel.Percent 设置为 15。

    如果 15 与之前的值不同,observable 将负责通知必要的各方(也称为“订阅者”),因此所有必需的操作(例如视图更新)都可以发生。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-29
    • 2021-12-03
    • 1970-01-01
    相关资源
    最近更新 更多