Javascript 剔除绑定顺序/无可观测项
我有一个简单的viewmodel:Javascript 剔除绑定顺序/无可观测项,javascript,knockout.js,Javascript,Knockout.js,我有一个简单的viewmodel: <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.u
<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;
});
}
这不是有效的URL
函数(){
var self=这个;
self.url=ko.observable();
self.isvalidull=ko.computed(函数(){
return!!$(“#url主机”).get(0).protocol;
});
}
我遇到的问题是,isvalidul
在输入更改时似乎没有被触发。我可以通过在ko.computed
函数中的任意位置添加self.url()
来解决这个问题。这看起来像是ko。computed
只有在它包含对可观察对象的调用时才会被触发,这实际上是有意义的
但是,通过向上面的代码添加self.url()
,$(“#url host”)
href
属性实际上仍然是未定义的。这意味着isvalidul
在attr
集绑定之前发生。我的问题有两个:
如何确保在运行isvalidul
计算函数之前设置attr
值
似乎isvalidul
应该取决于attr
绑定的完成,而不是值。有没有合适的方法
你有没有尝试过用一个空白值初始化你的可观测值,以阻止它被未定义
self.url = ko.observable('');
然后在您的computed中引用self.url()(我认为您正确地假设了computed应该依赖于您的案例中的可观察对象)
您还可以将valueUpdate绑定添加到输入:
<input data-bind="value: url, valueUpdate: keyup">
这样,每次按键时值都会更新,而不是在输入模糊时更新
除此之外,我要说的是,在isvalidul运行之前,不需要设置attr值。它将在每次更改输入值时运行
我已经用这段代码创建了一个。您可以使用“节流”扩展器延迟计算的可观测值的评估:
self.isValidUrl = ko.computed(function () {
self.url();
return !!$("#url-host").get(0).protocol;
}).extend({ throttle: 1 });
但是,请注意,可观察的“url”仅在输入字段失去焦点时更新,而不是在您键入时更新。不清楚您试图实现什么。但是使用knockoutjs可以避免这种dom选择,特别是在分配url时
我创建了一个大致符合我猜想您可能需要的
self.isValidUrl = ko.computed(function () {
return !!URI(self.url()).protocol();
});
我不得不求助于Uri.js库,因为我找不到从纯javascript字符串中获取协议的方法。ad1。只要调用ko.applyBindings()
就会遍历DOM并解析所有绑定。url
变量当时仍然是未定义的
,因为这就是初始化它的方式
公元2年。此外,正如您正确指出的那样,计算的
变量应该取决于可观察的
。如果您不想这样做(无论出于何种原因),您仍然可以订阅您的url
observable,并在回调中参考href
属性。看这里
我不确定这里是否存在时间问题:
是否显示验证消息的确定是键入真值而不是假值。请参阅下面的html或此链接
锚的协议在所有浏览器中的行为似乎并不相同。在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>
self.isvalidull=ko.computed(函数(){
var trigger=self.url();//触发器重新计算
return!!$(“#url主机”).get(0).protocol;
});
这不是有效的URL
这没有任何区别(如果我将其初始化为特定值,则相同)。我想我的主要问题是如何创建一个依赖于从DOM计算出的值的计算可观测值,而不是一般的可观测值。好吧,它应该与未定义的值有所不同。您是否在计算机中放置了断点,并查看在输入文本时是否命中了断点?如果不将self.url()
添加到computed
函数中,您需要将self.url放入计算机中。这就是计算的要点,它们是根据一个可观测的数据计算出来的。看看我的小提琴,让我知道你有什么问题,因为我认为它正在做你想要的事情,尽管你需要扩展is-valid方法来做一些实际的检查。为什么要从dom而不是url变量获取url?@bircadian the
可以像位置对象一样使用self.url()
返回输入值,而不是锚点,但您将输入值设置为锚点!所以,当你更新输入,你更新变量,你更新isvalidCan不明白为什么这个答案被否决,这似乎是最好的方法对我来说。一般来说,您应该避免从淘汰模型中访问任何UI元素。@DoctorMick我这样做只是为了可以将
用作位置对象;我也可以在运行中创建一个基本上做相同的事情,但通常的做法是将computed
函数的可观察依赖项调用为noop,以使其正确触发?@ExplosionPills不,这实际上表明您以错误的方式应用了基本概念。当可观察到的“url”的内容发生变化时,视图将被更新,目前为止还没有问题。但是,您正在从视图中读取一个值,该值是根据“url”的新值生成的,这是错误的,视图从不生成任何数据(除了直接用户输入)。此逻辑属于ViewModel,因此您应该使用self.URL()
中的内容在computed observable中实际实现URL验证,并且不要做这种肮脏的把戏;)(当然也可以接受这种情况)在这种情况下,我如何使用self.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>