当keyup触发保存时保持光标位置的最佳实践

时间:2015-03-13 19:12:33

标签: javascript backbone.js keyup

我正在使用Backbone.js。在我看来,我有textarea keyup绑定到这样的函数(但请参阅下面的编辑):

this.model.save({text: self.$('textarea').val()}, {patch: true});

在视图的initialize功能中,我将模型的change事件绑定到视图的render功能:

initialize: function() {
  this.listenTo(this.model, 'change', _.bind(this.render, this));
},

麻烦的是,当用户输入textarea时,会发生以下事件序列:

  1. keyup事件触发。
  2. keyup处理程序在模型上调用save
  3. save的调用会触发模型的change事件。
  4. 观看模型change事件的视图会调用render
  5. 在DOM中替换textarea
  6. textarea不再聚焦,文本光标位置丢失。
  7. 对于这种情况,texarea keyup事件需要触发同步的最佳做法是什么?我考虑过的一些选择:

    1. 不要将change绑定到render。缺点:如果模型数据因用户输入以外的任何内容而发生变化,则textarea不会自动更新。
    2. 读取并记住render开头的光标位置。将光标位置设置在render的末尾。缺点:取决于浏览器支持不稳定的游标操作功能。
    3. keyup处理程序中,在视图上设置一个临时属性,告诉它不要重新渲染。保存模型后取消设置。缺点:感觉像意大利面条代码,与Backbone的结构作斗争。
    4. 我有没有看到的选择?你推荐上面的一个选项吗?

      修改

      我并不想分散注意力,但是因为它出现在其中一个答案中:我没有直接绑定到keyup,而是将其与{{1}中介}}。因此,事件处理程序仅在用户停止键入时运行,由自上一个_.debounce以来经过的一定时间量定义。

1 个答案:

答案 0 :(得分:1)

首先,我想劝阻这一点,因为在keyup上保存模型似乎很奇怪。如果有一个用例确实需要这个,我建议至少使用input事件 - 否则每次用户按下箭头键,shift,ctrl时你最终都会保存模型等

我认为您还希望将输入事件去抖500毫秒左右,实际上并没有保存模型每次单次击键。

在第1点处理你的评论:

  

缺点:如果模型数据由于除了以外的任何内容而发生变化   用户输入时,textarea不会自动更新

你需要问问自己发生这种情况的可能性,以及如果要发生这种情况,重新审视的重要性。

最后,如果你确定这确实可能是,那么重新渲染视图很重要,那么你可以试试这样的事情

http://jsfiddle.net/nuewwdmr/2/

此处的重要部分之一是将模型属性名称映射到输入的名称字段。我在这里所做的是遵循你上面描述的一系列事件。不同之处在于,当模型更改时,我们检查更改的属性并更新模板中相应元素的值。

这在一个非常简单的情况下工作正常,这是一个快乐的路径,用户以“正常”的方式输入输入。但是,如果用户决定返回输入的开头并更改字母以将其大写,例如,在模型中发生更改事件后,光标将跳转到字符串的末尾。

这里你需要的行为实际上是双向数据绑定,这绝不是微不足道的,特别是Backbone给出了Backbone View的功能很少。

我的建议是你的观点1

  

不要将更改绑定到渲染

修改

如果您想进一步了解模型/视图绑定,可以查看两个库:

stickit

epoxy

我之前使用过stickit,它很好。不是很好。对于简单绑定是可以的,例如将“顶级”模型属性绑定到输入元素。一旦进入嵌套属性,您将遇到问题,然后您将不得不研究Backbone Deep Model等内容。

就像我说的那样,Backbone的View并没有提供太多功能。如果你有时间我建议使用React组件代替Backbone Views,或者看看ampersand必须提供的一些有趣的东西。