Javascript 剔除绑定顺序/无可观测项

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

我有一个简单的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.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>