【问题标题】:When using AngularFire, the cursor jumps to end of field while typing使用 AngularFire 时,键入时光标会跳到字段末尾
【发布时间】:2014-10-09 12:06:24
【问题描述】:

我设置了一个可以编辑一个字段的小型示例应用程序。但是,当我在该字段中输入内容时,内容会不断恢复到一秒钟前。我正在寻找 AngularFire 的修复程序,使其正常工作,或者我只是没有正确初始化它的 RTFM。此时 bindTo() 不可用,我根本无法继续使用 AngularFire。

这是完整的示例(您可以在 http://jsbin.com/wabafu/3 打开它):

<!DOCTYPE html>
<html ng-app="myapp">
  <head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.14/angular.min.js"></script>
    <script src='https://cdn.firebase.com/js/client/1.0.19/firebase.js'></script>
    <script src='https://cdn.firebase.com/libs/angularfire/0.8.0/angularfire.min.js'></script>
    <script>
      var app = angular.module("myapp", ["firebase"]);
      function MyController($scope, $firebase) {
        var ref = new Firebase("https://stackoverflow25331760.firebaseIO.com/"),
            syncObject = $firebase(ref).$asObject();
        syncObject.$bindTo($scope, "data");
      }
    </script>
  </head>
  <body ng-controller="MyController">
    <h3>
      <input type="checkbox" ng-model="EditMode"> Enable Editing
    </h3>
    <div ng-if="EditMode">
      <input type="text" ng-model="data.SyncValue" style="width:100%">
    </div>
    <div ng-if="!EditMode">
      {{data.SyncValue}}
    </div>
  </body>
</html>

仅在一个浏览器中打开时运行流畅,但在多个浏览器中打开时,我不能输入超过一两个单词,而文本内容会恢复到几次击键前并且光标移动到末尾字段。

我想发生的事件是:

  1. 我输入,值在 angularjs 中更新(好)
  2. Angularfire 将新值发送到 firebase (GOOD)
  3. Firebase 将值发送到其他浏览器(在我继续输入时)(好)
  4. 其他浏览器接收新值并更新其 html (GOOD)
  5. 其他浏览器将值重新发送回 Firebase,就好像它是新信息一样(真的很糟糕)
  6. Firebase 收到此回显的过时值并将其推回给我 (BAD)
  7. 我的浏览器获得了这个旧值,由于它与我的文本字段中的现在不同,我的 fiedl 的内容被还原 (BAD)

我想象的过程错了吗?我应该怎么做才能停止第 5 步?

附:在测试时,我发现我可以通过快速输入几个字符然后等待 2 秒,重复 #7 来解决问题。这样在同步回显时值不会改变,我的光标也不会跳跃。

P.P.S.为了缩小范围,我制作了一个复选框,用于控制数据是显示在字段中还是仅显示在只读 div 中。即使第二个浏览器只显示数据,这种回显/还原行为仍然存在于第一个浏览器中。将数据正确存储在 Firebase 中的唯一方法是,如果我一次只有一个浏览器使用它。

【问题讨论】:

  • 请在您的问题中包含最少的相关代码。
  • 我已经包含了最小的代码并测试了它仍然有问题的行为。
  • 在使用共享白板时,您可能需要考虑不同的数据模型。无论连接速度有多快,让多个客户端修改完全相同的状态都会导致此类问题。如果您以 Firebase 的绘图白板为例,您会发现每个用户都在绘制自己的线条;这只是每个人都看到的组合图像。您可以为您的用例做类似的事情吗?所以仍然共享板,但给每个用户他/她自己的“编辑”区域。
  • 您也可以使用transaction 将新字符添加到数据中。在transaction 中,您传入节点的现有值并返回新值,因此此时您可以完全控制。
  • 感谢交易提示,这可能是解决此问题的一种方法。但是我如何防止第 5 步开始呢?对我来说,这似乎是一个 AngularFire 错误。刚刚坐在那里的浏览器 B(此字段中没有光标)应该能够接收并显示更新的值,而无需将其回显到 firebase,就好像“哦,看,我有一个新值给你”

标签: angularjs firebase angularfire


【解决方案1】:

通过在输入上添加去抖动,我取得了很好的成功。

<input type="text" ng-model="data.field" 
    ng-model-options="{ updateOn: 'default blur', debounce: {'default': 500, 'blur': 0} }" />

另外,$bindTo 在这里并不是绝对必要的。手动保存数据并跳过 $bindTo 并不是特别难。

$scope.data = $firebase(new Firebase(...)).$asObject();

<input type="text" ng-model="data.field" ng-blur="data.$save()" />

【讨论】:

  • 我喜欢使用简单的 data.save() 手动方法的干净程度
  • 我尝试使用 ng-keyup 而不是 ng-blur 进行此操作,但问题行为仍然存在(直到添加去抖动),以便缩小范围,这不是 bindTo 的问题。对于白板情况仍然不理想,因为它应该保持同步,但是有人可以整天将光标留在字段中,以为其他人看到他们输入的内容而他们没有看到。请参阅jsbin.com/wabafu/4 Debounce 几乎是答案,只是在我停止打字后它的行为与淘汰赛的油门功能不同。有时我将不得不为此打开一个单独的问题。
  • 明白了!!我做了与你的第二个示例相同的操作,除了 ng-blur,我使用了 ng-change="data.$save()" 就是这样,甚至不需要 ng-model-options 属性,它现在可以实时同步打字没有错误。当我想要 ng-change 时使用 ng-keyup 事件时会出现问题。
  • 太棒了。我们还将在 0.8.1 中对此进行一些优化。我已经成功地使用 $bindTo 和默认值运行并且没有任何跳跃或奇怪。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-24
  • 2012-01-03
  • 2020-07-29
  • 2020-02-21
  • 2011-08-17
  • 2011-10-25
相关资源
最近更新 更多