0

我有一个简单的视图模型:

<input data-bind="value: url">
<a id=url-host data-bind="attr: { href: url }"></a>
<div data-bind="visible: isValidUrl">
    This is not a valid URL
</div>

function () {
    var self = this;
    self.url = ko.observable();

    self.isValidUrl = ko.computed(function () {
       return !!$("#url-host").get(0).protocol;
    });
}

我遇到的问题是isValidUrl输入更改时似乎没有触发。我可以通过在函数self.url()内添加任何位置来解决此问题。ko.computed似乎ko.computed只有在它包含对可观察对象的调用时才会触发,这实际上是有道理的。

但是,通过添加self.url()到上面的代码中,$("#url-host") href属性实际上仍然是undefined. 这意味着在set 绑定之前isValidUrl发生。我的问题是双重的:attr

  1. 如何确保在计算函数运行之前attr设置该值?isValidUrl
  2. 看起来isValidUrl应该取决于attr绑定的完成而不是值。有没有合适的方法来做到这一点?
4

5 回答 5

2

目前尚不清楚您要达到的目标。但是您使用 knockoutjs 来避免这种 dom 选择,尤其是在分配 url 时。

我创建了一个小提琴,它大致完成了我怀疑你可能想要的

self.isValidUrl = ko.computed(function () {
   return !!URI(self.url()).protocol();
});

我不得不求助于 Uri.js 库,因为我找不到从纯 javascript 字符串中获取协议的方法。

于 2013-07-08T15:07:38.800 回答
0

我不确定这里是否存在时间问题:

  1. 是否显示验证消息的确定是关闭true值而不是false。请参阅下面的 html 或此小提琴

  2. 锚的协议似乎在所有浏览器中的行为都不相同。在 Firefox 协议中总是返回“http”,而在 IE 中它确实返回您输入的内容。对于其他人来说可能会有所不同。

在这种情况下,让isValidUrl计算为多次触发确实需要一个触发器,在这个例子中,我使用了 url observable。

self.isValidUrl = ko.computed(function () {
    var trigger = self.url(); // trigger re-evaluation
   return !!$("#url-host").get(0).protocol;
});

<div data-bind="visible: !isValidUrl()">
    This is not a valid URL
</div>
于 2013-07-08T16:29:10.090 回答
0

您可以使用“节流”扩展器来延迟计算 observable 的评估:

self.isValidUrl = ko.computed(function () {
    self.url();
    return !!$("#url-host").get(0).protocol;
}).extend({ throttle: 1 });

但是,请注意,可观察的“url”仅在输入字段失去焦点时更新,而不是在您输入时更新。

于 2013-07-08T15:05:17.760 回答
0

广告 1. 只要您调用ko.applyBindings()DOM,就会遍历所有绑定并解析。该url变量仍然undefined在那个时候,因为这就是您初始化它的方式。

广告 2. 此外,正如您正确指出的那样,computed变量应取决于observable. 如果您不想这样做(无论出于何种原因),您仍然可以订阅您的urlobservable 并在回调中引用该href属性。请参阅此处的文档

myViewModel.url.subscribe(function(newValue) {
  // use $("#url-host") here
  // ...
});
于 2013-07-08T15:34:32.273 回答
-1

您是否尝试过使用空白值初始化您的 observable,以阻止它未定义?

self.url = ko.observable('');

然后在你的计算中引用 self.url() (我认为你假设计算应该依赖于你的情况下的可观察对象是正确的)。

您还可以将 valueUpdate 绑定添加到您的输入:

<input data-bind="value: url, valueUpdate: keyup">

以便在每次按键时更新该值,而不是在您模糊输入时更新该值。

除此之外,我想说您不需要在 isValidUrl 运行之前设置 attr 值。每次更改输入值时它都会运行。

我用这段代码创建了一个jsFiddle 。

于 2013-07-08T15:01:41.403 回答