敲除绑定顺序/不带可观察性

Knockout binding order / without observables

本文关键字:可观察性 定顺序 绑定      更新时间:2023-09-26

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

<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似乎不会被触发。我可以通过在ko.computed函数内的任何位置添加self.url()来解决此问题。ko.computed似乎只有在包含对可观察对象的调用时才会被触发,这实际上是有意义的。

然而,通过将self.url()添加到上面的代码中,$("#url-host") href属性实际上仍然是undefined。这意味着isValidUrl出现在attr集合绑定之前。我的问题有两个:

  1. 如何确保在运行isValidUrl计算函数之前设置attr
  2. isValidUrl似乎应该取决于attr绑定的完成,而不是值。有合适的方法吗

目前还不清楚您想要实现什么。但是您使用knockoutjs来避免这种dom选择,尤其是在分配url时。

我创造了一把小提琴,大致可以做我怀疑你可能想要的

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

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

您可以使用"节流"扩展器来延迟对计算的可观测值的评估:

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

但是,请注意,可观察的"url"只有在输入字段失去焦点时才会更新,而不是在您打字时。

ad 1。一旦调用ko.applyBindings(),就会遍历DOM并解析所有绑定。url变量当时仍然是undefined,因为这就是初始化它的方式

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

myViewModel.url.subscribe(function(newValue) {
  // use $("#url-host") here
  // ...
});

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

  1. 是否显示验证消息的确定是关闭true值,而不是false。请参阅下面的html或这个fiddle。

  2. 锚的协议在所有浏览器中的行为似乎并不相同。在firefox协议中,它总是返回"http",而在IE中,它确实返回您键入的内容。其他协议可能不同。

在这种情况下,要将isValidUrl计算为触发多次,确实需要触发器,在本例中,我使用了可观察的url。

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>

您是否尝试过用空白值初始化您的可观察值,以防止其未定义?

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

然后在你的computed中引用self.url()(我认为你假设computed应该依赖于你的情况下的observable是正确的)。

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

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

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

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

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