在字段编辑期间关闭反应性
Turning off Reactivity during field edit
我正在处理一个响应式表单,需要解决一个问题。问题是我的用户使用 tablets/cellphones 的手机连接速度较慢,有时甚至连接松动。重新建立连接后,Meteor 将触发所有 DDP 消息,从而触发表单中的 Reactivity,从而覆盖用户已执行但未保存的任何表单输入。
所以我想到了将临时值保存在文档中的想法,这样当用户更改表单输入时,更改将存储在 "temp" 值中,直到他们点击保存,此时我只是将临时值复制到实际值并将其清空。显示时我只是检查是否有临时值,如果有则显示,如果没有则显示原始保存的值。
这对于非文本字段(如单选按钮和复选框)非常有效,但对于文本输入则效果不佳。
问题似乎与反应性有关。当用户键入时,我在 change
和 keydown
上设置了一个偶数处理程序(我也尝试过 keypress
和 keyup
),它只是触发对临时值的更新,例如这个:
'change .responseInput, keydown .responseInput': function(event, tmpl) {
var response = Blaze.getData(tmpl.$('.headerDiv')[0]);
var val = response.lastResponseValue;
if (!val) {
val = new ResponseValue({
response_id: response.id
});
}
val.tempValues = getSelectedValues(tmpl.$('div.responseDiv'));
val.save();
}
在此事件处理程序中,response.lastResponseValue
只是 returns 最后一个响应值(我维护用户输入值的历史记录)并且 getSelectedValues()
接受一个 DOM 元素代表表单控件周围的 DIV 并删除选定的值,这些值可能是 textbox/textarea 的单个字符串,或者复选框的字符串值数组。这些作品按预期工作。
不起作用的是 val.save()
。选择文本输入字段并快速键入时,体验是键入的文本是随机的 skipped/ignored/removed,很可能是由于反应性。我尝试将事件处理程序包装在 Tracker.nonreactive()
中以关闭反应性,但这似乎没有帮助。我猜是因为它不是反应性的 save()
,而是 find()
.
我考虑过将临时值的内容分离到一个单独的文档中。然后实际值不会被触及,只有临时值附加到它,但我最终需要编写仍然返回临时值的代码,否则原始问题根本无法解决,在这种情况下我我想我会回到同一条船上,用户和反应性之间存在竞争条件。
有没有办法暂时关闭 Meteor/Blaze 中文档的反应性?或者是否有更好的 method/pattern 我可以遵循它可以使这项工作更好?
您的表单元素根本不应连接到任何反应值,否则它们将像您看到的那样被清除,并且在热代码推送期间也是如此。
相反,您应该在呈现模板时只初始化一次表单。如果在用户编辑表单时基础值发生变化,则表单不会自动更新,这在大多数用例中都是合乎逻辑的。
您仍然需要在用户进行更改时更新本地存储,以便在发生热代码推送时您可以将表单恢复到 已编辑 状态.
看看这个,它可以轻松处理所有问题:
蒂姆
我正在处理一个响应式表单,需要解决一个问题。问题是我的用户使用 tablets/cellphones 的手机连接速度较慢,有时甚至连接松动。重新建立连接后,Meteor 将触发所有 DDP 消息,从而触发表单中的 Reactivity,从而覆盖用户已执行但未保存的任何表单输入。
所以我想到了将临时值保存在文档中的想法,这样当用户更改表单输入时,更改将存储在 "temp" 值中,直到他们点击保存,此时我只是将临时值复制到实际值并将其清空。显示时我只是检查是否有临时值,如果有则显示,如果没有则显示原始保存的值。
这对于非文本字段(如单选按钮和复选框)非常有效,但对于文本输入则效果不佳。
问题似乎与反应性有关。当用户键入时,我在 change
和 keydown
上设置了一个偶数处理程序(我也尝试过 keypress
和 keyup
),它只是触发对临时值的更新,例如这个:
'change .responseInput, keydown .responseInput': function(event, tmpl) {
var response = Blaze.getData(tmpl.$('.headerDiv')[0]);
var val = response.lastResponseValue;
if (!val) {
val = new ResponseValue({
response_id: response.id
});
}
val.tempValues = getSelectedValues(tmpl.$('div.responseDiv'));
val.save();
}
在此事件处理程序中,response.lastResponseValue
只是 returns 最后一个响应值(我维护用户输入值的历史记录)并且 getSelectedValues()
接受一个 DOM 元素代表表单控件周围的 DIV 并删除选定的值,这些值可能是 textbox/textarea 的单个字符串,或者复选框的字符串值数组。这些作品按预期工作。
不起作用的是 val.save()
。选择文本输入字段并快速键入时,体验是键入的文本是随机的 skipped/ignored/removed,很可能是由于反应性。我尝试将事件处理程序包装在 Tracker.nonreactive()
中以关闭反应性,但这似乎没有帮助。我猜是因为它不是反应性的 save()
,而是 find()
.
我考虑过将临时值的内容分离到一个单独的文档中。然后实际值不会被触及,只有临时值附加到它,但我最终需要编写仍然返回临时值的代码,否则原始问题根本无法解决,在这种情况下我我想我会回到同一条船上,用户和反应性之间存在竞争条件。
有没有办法暂时关闭 Meteor/Blaze 中文档的反应性?或者是否有更好的 method/pattern 我可以遵循它可以使这项工作更好?
您的表单元素根本不应连接到任何反应值,否则它们将像您看到的那样被清除,并且在热代码推送期间也是如此。
相反,您应该在呈现模板时只初始化一次表单。如果在用户编辑表单时基础值发生变化,则表单不会自动更新,这在大多数用例中都是合乎逻辑的。
您仍然需要在用户进行更改时更新本地存储,以便在发生热代码推送时您可以将表单恢复到 已编辑 状态.
看看这个,它可以轻松处理所有问题:
蒂姆