Knockout JS,从 websocket 实时更新数据
Knockout JS, live updating data from websocket
我正在尝试从 websocket 加载数据以使用 knockout 和 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 获取的数据,需要更新值,它总是显示第一个值,但之后的所有内容都给出错误。
由于我对编码非常陌生,所以我真的迷失了淘汰赛。
下面是您的用例的最小工作示例。您可以 运行 看看它的作用:
// 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()
后,您仍然需要打开(也称为“展开”)可观察对象以查看其中的内容。这就是为什么我上面的代码需要两个步骤,valueAccessor()
和 ko.unwrap()
.
- 什么时候它不是可观察的? - 您可以自由绑定到视图中的文字值 (
data-bind="gaugeValue: 15"
),或绑定到不可观察的视图模型当视图模型具有 {basicEfficiency: 15}
时的属性 (data-bind="gaugeValue: basicEfficiency"
)。在所有情况下,valueAccessor()
都会给你 那个 值,无论是否可观察到。
- 为什么使用
ko.unwrap(boundValue)
而不是 boundValue()
? - 前者适用于文字值和可观察值,后者仅适用于可观察值。在绑定处理程序中,支持这两种用例是有意义的。
更新到达后,例如通过 WebSocket,不要尝试重新应用任何绑定或重新初始化任何东西。
您需要做的就是更改视图模型中相应可观察对象的值。通过调用它来更改可观察值的值:myViewModel.Percent(15);
会将 myViewModel.Percent
设置为 15.
如果 15 与之前的值不同,可观察对象将负责通知必要的各方(也称为“订阅者”),因此所有必需的操作(例如视图更新)都可以发生。
我正在尝试从 websocket 加载数据以使用 knockout 和 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 获取的数据,需要更新值,它总是显示第一个值,但之后的所有内容都给出错误。 由于我对编码非常陌生,所以我真的迷失了淘汰赛。
下面是您的用例的最小工作示例。您可以 运行 看看它的作用:
// 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()
后,您仍然需要打开(也称为“展开”)可观察对象以查看其中的内容。这就是为什么我上面的代码需要两个步骤,valueAccessor()
和ko.unwrap()
.- 什么时候它不是可观察的? - 您可以自由绑定到视图中的文字值 (
data-bind="gaugeValue: 15"
),或绑定到不可观察的视图模型当视图模型具有{basicEfficiency: 15}
时的属性 (data-bind="gaugeValue: basicEfficiency"
)。在所有情况下,valueAccessor()
都会给你 那个 值,无论是否可观察到。 - 为什么使用
ko.unwrap(boundValue)
而不是boundValue()
? - 前者适用于文字值和可观察值,后者仅适用于可观察值。在绑定处理程序中,支持这两种用例是有意义的。
- 什么时候它不是可观察的? - 您可以自由绑定到视图中的文字值 (
更新到达后,例如通过 WebSocket,不要尝试重新应用任何绑定或重新初始化任何东西。
您需要做的就是更改视图模型中相应可观察对象的值。通过调用它来更改可观察值的值:
myViewModel.Percent(15);
会将myViewModel.Percent
设置为 15.如果 15 与之前的值不同,可观察对象将负责通知必要的各方(也称为“订阅者”),因此所有必需的操作(例如视图更新)都可以发生。