【问题标题】:Simple Knockout + Bootstrap Typeahead plugin race conditionSimple Knockout + Bootstrap Typeahead 插件竞争条件
【发布时间】:2013-01-21 01:15:25
【问题描述】:

我有一个用于 Knockout.js 的 very simple Bootstrap Typeahead binding (jsFiddle),如下所示:

ko.bindingHandlers.typeahead = {
    init: function (element, valueAccessor) {
        var $e = $(element),
            source = valueAccessor();

        $e.typeahead({
            source: source,
            minLength: 0
        });
    },
};

它的用法很简单:

<input data-bind='typeahead: source, value: item,
                  valueUpdate: "afterkeydown"' />

绑定在jsFiddle 中按预期工作。但是,当使用 RequireJS 加载时,它并不总是按预期工作。由于 Knockout 和 jQuery 并行加载,似乎存在竞争条件。

如果我查看绑定输入元素的 change 事件处理程序,如果 jQuery 是处理程序,则绑定按预期工作。如果 Knockout 是 change 事件的处理程序,例如,如果您键入“alp”,并且 Typeahead 建议“Alpha”,并且您从 Typeahead 下拉列表中选择“Alpha”,那么 &lt;input&gt; 元素将显示选定的文本(“Alpha”),但绑定的 observable 将是“alp”。

在当前系统中,Typeahead 绑定无法直接修改给定的 observable,因此传递 { source: src, observable: item } 无法解决问题。这个Typeahead绑定的作用只是更新绑定输入区的内容。

我已经尝试过从绑定中触发相关事件,例如“keydown”、“keypress”和“keyup”,但由于显而易见的原因,这不是一个非常灵活的选项。

我怀疑这个问题与 RequireJS 的不确定性有关,Typeahead 插件的工作与否取决于首先加载的是 jQuery 还是 Knockout。特别是,似乎通过使用 RequireJS 的 shim 使 jQuery 成为 Knockout 的依赖项(即首先加载 jQuery)解决了这个问题:

requirejs.config({
   shim: {
      knockout: { deps: ['jquery'] },
   }
 });

这看起来很奇怪,我想更好地了解这里发生的事情以及这是否是问题的合理解决方案 - 即我是否真的在这里解决了潜在问题,或者问题是否会在后续版本的 Knockout 中突然出现或 jQuery。

如果有任何想法,我将不胜感激。

编辑

您可以通过按顺序加载脚本来简单地复制问题,例如:

<script src='knockout.js'></script>
<script src='jquery.js'></script>

这是jsFiddle exhibiting the issue.

按上述顺序插件会失败;否则它将按预期工作。

无论如何,RequireJS 的配置是这样的:

requirejs.config({
  baseUrl: "/script",
  shim: {
    knockout: { deps: ['jquery'] }, # remove this for race condition
  }
});

main 的简化版本具有require(['jquery', 'knockout', 'bindings'], ...),其中bindings 定义了敲除处理程序。 bindings.js 文件实际上以 define(['knockout', 'jquery'], ...) 开头。

在这种情况下,虽然问题不是 RequireJS,而是脚本的顺序。

【问题讨论】:

  • 您是否将绑定保存在单独的模块中?是什么阻止您访问define(['ko', 'jq'], function(){ //bindings })?然后在您的视图模型模块中,您将 bindings 作为依赖项加载。
  • @JonJaques:是的,绑定在一个单独的模块中,这取决于两者。问题似乎不是依赖引起的,而是执行顺序引起的。
  • 嗯,你能发布你的视图模型的模块代码吗?不需要整个东西,只是需要的东西,以及您实例化/绑定视图模型的部分?
  • 你用这段代码为我节省了几个小时!谢谢!

标签: knockout.js jquery knockout-2.0


【解决方案1】:

我怀疑您以某种方式缺少依赖项。可能是引导程序。

在此处查看我的示例。你看看垫片配置是对的。 http://jsfiddle.net/jaquers/sfvy9/2/

requirejs.config({
    shim: {
        'bootstrap': {
            deps: ['jquery'],
            exports: 'jQuery.fn.typeahead'  // we can't test for more than one object                   
        }
    }
});

【讨论】:

  • 注意:小提琴不再起作用,但如果您设置了平面目录结构,该代码应该可以运行。
  • 谢谢乔恩。问题是 Knockout 和 jQuery 的顺序。如果 jQuery 先出现,Knockout 会检测到它并使用 jQuery 事件绑定。期望 Knockout 旨在检测和利用 jQuery 并且排序脚本以便首先加载 jQuery 将导致预期的结果,这似乎相当安全(根据我的粗略知识)。您可以在我对问题的编辑中看到该问题。干杯
猜你喜欢
  • 1970-01-01
  • 2018-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多