Javascript 主干模型更改事件中具有更新属性的无限循环
我使用主干和ReactJS将一些HTMLJavascript 主干模型更改事件中具有更新属性的无限循环,javascript,backbone.js,infinite-loop,backbone-events,Javascript,Backbone.js,Infinite Loop,Backbone Events,我使用主干和ReactJS将一些HTMLdivs(让我们称它们为盒子)堆叠在另一个div(让我们称这个容器)中。用户可以放大这个容器,也可以放大框(与CSS缩放属性无关)。当容器上触发缩放事件时,我计算放大框的总高度,并用堆栈的新高度更新容器。实际的代码很麻烦,下面的代码模拟了导致无限循环的确切场景 在下面的代码中,用户更改ClickButton模型上的缩放值。基于zoom值,我计算新的j并更新它。当j改变时,我也更新了k。现在我处在一个无限循环中,不断增加k的值。通过点击“点击”按钮对代码进行
div
s(让我们称它们为盒子)堆叠在另一个div
(让我们称这个容器)中。用户可以放大这个容器,也可以放大框(与CSS缩放属性无关)。当容器上触发缩放事件时,我计算放大框的总高度,并用堆栈的新高度更新容器。实际的代码很麻烦,下面的代码模拟了导致无限循环的确切场景
在下面的代码中,用户更改ClickButton模型上的缩放值。基于zoom
值,我计算新的j
并更新它。当j
改变时,我也更新了k
。现在我处在一个无限循环中,不断增加k
的值。通过点击“点击”按钮对代码进行测试。变量k
冲到100(故意在100处中断,否则浏览器将冻结)
我的理解是:
看起来,当我在更改处理程序上更新k或主干模型中的任何内容时,它会创建另一个更改事件。上一个事件结束后,此新事件开始执行。但是,对于函数调用this.hasChanged(“j”),这个新事件仍然返回true,它发生在上一个事件之前,并在上一个事件中处理
当前解决方案:
我使用{silent:true}
选项作为主干set
方法的输入,并成功地停止了无限循环
我想用另一种方法来实现这一点,而不抑制更改事件,因为我的HTML页面更新依赖于更改事件。我的ReactJS应用程序连接到模型,并更新模型更改视图
有人知道更好的解决办法吗
var ClickButton=Backbone.Model.extend({
默认值:函数(){
返回{
类名:“显示”,
缩放:0,
j:0,
k:0,
儿童:[],
}
},
初始化(){
getElement(“缩放”).value=this.get(“缩放”);
getElement(“zoomchanged”)。值=0;
关于“变更”,功能(e){
如果(本条已更改(“j”)){
getElement(“j”).value=this.get(“缩放”);
如果(此项获得(“k”)<100){
//刚刚添加了100个,您的浏览器不会被卡住
this.set(“k”),parseInt(this.get(“k”))+1);
getElement(“k”).value=parseInt(this.get(“k”));
}
}
如果(此.hasChanged(“缩放”)){
getElement(“zoomchanged”).value=parseInt(getElement(“zoomchanged”).value)+1;
console.log(this.get(“zoom”);
getElement(“缩放”).value=this.get(“缩放”);
this.set(“j”,this.get(“zoom”);
}
});
}
});
var clickButton=新的clickButton();
var button=getElement(“按钮”);
按钮。addEventListener(“单击”),功能(e){
var currentValueOfZoom=点击按钮。获取(“缩放”);
单击按钮。设置(“缩放”,当前缩放值+1);
}).约束(这个);
//助手
函数getElement(类名){
返回单据.getElementsByClassName(类名)[0];
}
输入{
宽度:35px;
}
div#holder{
显示器:flex;
}
div#holder输入{
右边距:23px;
}
K:
J:
缩放:
缩放更改次数:
点击
主干网的静默:true
可以防止这种行为。但是,如文档中所述,更好的解决方案是传递一个特定的标志(例如我在下面的代码段中传递并检查的ignore:true
标志)
从主干文档:
一般来说,在调用发出事件的函数(model.set、collection.add等)时,如果要防止触发事件,可以将{silent:true}作为选项传递。请注意,这很少,甚至从来都不是一个好主意。在选项中传递一个特定的标志以供事件回调查看,并选择忽略,通常效果会更好
虽然针对您的情况提供了一个工作补丁,但我还是想分享一下最佳实践
发生了什么事?
仅返回通过集合所做的最新更改,不跟踪任何其他后续更改,除非这些更改是在相关触发事件中进行的。一旦集合
完成,对集合
的任何后续调用都将覆盖该集合
由于在一般的change
事件中更改zoom
、j
和k
,因此任何后续的set
都会触发一个新的change
事件,其中hasChanged
始终返回true,因为changed
属性如下所示:
{
zoom: 1,
j: 1,
k: 100,
}
如何解决这个无限循环?
可以做很多事情来简化和改进您的模型。首先,不要在主干模型中使用DOM。这是视图的工作,所以在您的情况下做出反应
记住这一点,使用处理程序(change:[attribute]
)
尽管如此,我不确定主干模型是否是处理按钮点击的好选择。但话说回来,您还没有共享React代码…谢谢。这就解决了问题+1因为我从来不知道我可以将自定义数据作为选项传递。我一直认为选项就像主干内部指令一样,{silent:true}将在更改事件时抑制。
{
zoom: 1,
j: 1,
k: 100,
}
var ClickButton = Backbone.Model.extend({
defaults: {
zoom: 0,
j: 0,
k: 0,
},
initialize() {
this.listenTo(this, {
'change:zoom': this.onZoomChange,
'change:j': this.onJChange
});
},
onZoomChange(model, value, options) {
this.set("j", this.get("zoom"));
},
onJChange(model, value, options) {
this.set("k", parseInt(this.get("k")) + 1);
}
});