Knockout.js 选项标题如何影响敲除中的数据绑定

Knockout.js 选项标题如何影响敲除中的数据绑定,knockout.js,Knockout.js,我有两组几乎相同的代码,它们之间唯一的区别是一个元素中有选项标题,另一个没有。没有选项Caption data的代码似乎正确绑定,而另一个似乎在绑定第一个元素后停止数据绑定。有人能解释一下我做错了什么,为什么数据绑定是这样工作的吗 示例1-不起作用,要查看,请选择以下选项之一- 示例2-工作正常- 脚本: var Program = function (programId, description) { this.ProgramId = programId; this.Descr

我有两组几乎相同的代码,它们之间唯一的区别是一个元素中有选项标题,另一个没有。没有选项Caption data的代码似乎正确绑定,而另一个似乎在绑定第一个元素后停止数据绑定。有人能解释一下我做错了什么,为什么数据绑定是这样工作的吗

示例1-不起作用,要查看,请选择以下选项之一-

示例2-工作正常-

脚本:

var Program = function (programId, description) {
    this.ProgramId = programId;
    this.Description = description;
};


var myViewModel = function () {
    var self = this;
    self.program = ko.observable();
    self.programId = ko.observable(-1);

    self.availablePrograms = ko.observableArray([
    new Program(1, "Program One"),
    new Program(2, "Program Two"),
    new Program(3, "Program Three")]);

    self.programId.subscribe(function (newValue) {
        self.program(self.availablePrograms()[newValue - 1]);
    });

};
非工作html:

<div>
    <select data-bind="options: availablePrograms, optionsText: 'Description', optionsValue: 'ProgramId', value: programId, optionsCaption: 'Select a Program'"></select>
</div>
<div>
    <input type="text" data-bind="value: program().Description" />
    <input type="text" data-bind="value: program().Description" />
    <input type="text" data-bind="value: program().ProgramId" />
</div>
<div>
    <select data-bind="options: availablePrograms, optionsText: 'Description', optionsValue: 'ProgramId', value: programId"></select>
</div>
<div>
    <input type="text" data-bind="value: program().Description" />
    <input type="text" data-bind="value: program().Description" />
    <input type="text" data-bind="value: program().ProgramId" />
</div>

工作html:

<div>
    <select data-bind="options: availablePrograms, optionsText: 'Description', optionsValue: 'ProgramId', value: programId, optionsCaption: 'Select a Program'"></select>
</div>
<div>
    <input type="text" data-bind="value: program().Description" />
    <input type="text" data-bind="value: program().Description" />
    <input type="text" data-bind="value: program().ProgramId" />
</div>
<div>
    <select data-bind="options: availablePrograms, optionsText: 'Description', optionsValue: 'ProgramId', value: programId"></select>
</div>
<div>
    <input type="text" data-bind="value: program().Description" />
    <input type="text" data-bind="value: program().Description" />
    <input type="text" data-bind="value: program().ProgramId" />
</div>


谢谢

浏览器控制台显示此错误:

未捕获类型错误:无法处理绑定“值:函数(){return program().Description}” 消息:无法读取未定义的属性“说明”

这是因为在第一种情况下(当不起作用时),
programId
的值在knockout执行绑定时不会改变(因为指定了optionsCaption,并且没有选择实际值)。所以
program
保持未定义状态,因为您没有使用任何值(
self.program=ko.observable();
)初始化它

在第二种情况下(工作时),在绑定过程中,knockout更新
programId
(以设置select的默认值),因此您的订阅将触发:

self.programId.subscribe(function (newValue) {
    self.program(self.availablePrograms()[newValue - 1]);
});
因此,
程序
被更新,并且值被正确填充

编辑:

出现了另一个问题:

当我选择一个程序时,到底发生了什么?如果program()为null,那么在选择程序后第一个输入元素如何显示值;另一方面,如果program()不为null,那么其他两个元素如何不被绑定

当knockout绑定第一个值时,抛出异常(因为未定义),绑定过程停止。但是,第一个绑定保持“活动”,其余的则不绑定。只是想澄清一下-由于绑定只执行一次,所以即使
program
值发生变化,其他字段也不会被绑定。这就是为什么它的行为如此怪异


注意:此讨论从注释复制粘贴到同一问题的其他答案,以确保在删除答案或注释的情况下不会丢失此讨论。

如果使用
选项caption
,如
程序()
将是
未定义的
,直到选择某个内容为止。您可以执行以下操作:



如果设置了
program()
observable,这将仅对其进行评估。

问题在于,您的输入绑定正试图使用
program
observable中找到的对象的属性。将标题添加到选择
选项
绑定时,没有初始值,因此
程序
最终没有值(
未定义
),因此一切都会发生故障

其他人已经提供了一种解决问题的方法,但还有一个问题仍然存在,即您没有充分利用这些绑定

select
元素的选定值不需要是字符串或其他简单值,它可以是任何值。与其绑定到补充id并查找相关程序,不如绑定到程序本身


函数ViewModel(){
this.selectedProgram=ko.observable();
this.availablePrograms=ko.observableArray(…);
}
然后,如果要访问所选程序的属性,请使用带有绑定的
,将上下文更改为所选程序


请注意,如果没有选定的程序,则不会显示输入。如果要使其可见,请在没有选定程序时使用虚拟对象

。。。
演示:

功能程序(程序ID,说明){
this.ProgramId=ProgramId;
这个。描述=描述;
}
函数ViewModel(){
this.selectedProgram=ko.observable();
this.availablePrograms=ko.observableArray([
新计划(1,“计划一”),
新计划(2,‘计划二’),
新计划(3,‘计划三’)
]);
}
var viewModel=新的viewModel();
applyBindings(viewModel,document.getElementById('content')
#内容分区{
边框:薄黑色实心;
}


正确,但是
程序
值将是
未定义的
而不是
空的
@Tanner谢谢,不过我还有一个后续问题。在有Options Caption的示例中,当我选择一个程序时,到底发生了什么?如果program()为空,那么在选择程序后第一个输入元素如何显示值;另一方面,如果program()为非空,那么其他两个元素如何不被绑定?@user2634253当knockout初始化输入字段时,它尝试绑定第一个项并标识
program()
未定义的
,但绑定已设置,但在随后的尝试中,它已注册为
未定义的
,因此不处理剩余项。这完全是猜测。@user2634253当knockout绑定第一个值时,抛出异常(因为
未定义),绑定过程停止。但是,第一个绑定保持“活动”,其余的则不绑定。这就是为什么它的行为如此怪异。顺便说一句,看看我的答案,了解当我选择一个程序时发生的具体情况。好的,我想我终于明白了。在页面加载时调用applyBindings(正确吗?),在第一个绑定时抛出异常,但是应用了绑定。由于绑定已应用,但具有无效的