问题描述
我不确定我了解Knockout.js在内部遵循的工作流程.我有一个使用映射插件动态定义的ViewModel.它的形状是:
I'm not sure I understand the workflow Knockout.js follows internally. I have a ViewModel that is defined dynamically, using the mapping plugin. Its shape is:
{ current: { foo: 'foo', bar: 'bar', id: 0 }
, ids: [1,2,3,4,5]
}
每个ids
都对应一个可以属于current
的值.现在,复杂性出现了,因为在填充我的viewModel的初始ajax请求中,服务器使用current: null
进行响应.我已经编写了将第一个id
从ids
列表中删除的代码,并运行另一个ajax查询来填充current
.看起来像这样:
Each of those ids
corresponds to a value that can belong in current
. Now, the complication comes in because in the initial ajax request to populate my viewModel, the server responds with current: null
. I have written code to take the first id
out of the list of ids
and run another ajax query to populate current
. That looks like this:
var ViewModel = function (data) {
var self = this;
ko.mapping.fromJS(data, {}, self);
self.head = function () {
if (self.promptIds().length != 0) {
var nextId = _.head(self.promptIds());
self.promptIds(_.tail(self.promptIds()));
$.getJSON("my-url" + "/" + nextId, function (data) {
self.current(ko.mapping.fromJS(data));
});
}
}
}
$('document').ready ( function () {
$.getJSON("view-model-route", function (data) {
viewModel = new ViewModel(data);
viewModel.head();
ko.applyBindings(viewModel);
});
});
请注意,在第二个块中,我创建了一个新的ViewModel
对象,并在其上调用了head()
.填充viewModel.current()
对象后,我将在完整的viewModel
上调用ko.applyBindings
.我可以确认所有尘埃落定后,viewModel.current
不是null
.但是我仍然遇到错误:
Notice that in the second block, I create a new ViewModel
object and I call head()
on it. Once the viewModel.current()
object is populated, I call ko.applyBindings
on the complete viewModel
. I can confirm that when all the dust settles, viewModel.current
is not null
. But I am still getting the error:
Uncaught TypeError: Unable to parse bindings.
Bindings value: text: current().foo
Message: Cannot read property 'foo' of null
我想做淘汰赛原本不打算做的事情吗?我是否需要另一层抽象?您将如何处理这种情况?
Am I trying to do something Knockout wasn't designed to do? Do I need another layer of abstraction? How would you approach this situation?
推荐答案
在调用ko.applyBindings
时首先评估绑定.
The bindings are first evaluated when you call ko.applyBindings
.
因此,如果此时您的current
属性包含null
,则通常会出现Cannot read property 'foo' of null
异常.
So if your current
property contains null
by that time then this it is normal that you get an Cannot read property 'foo' of null
exception.
对此问题有多种解决方案:
There are multiple solution to this problem:
-
使用空对象初始化
current
,因此将正确解析current().foo
(但其值为undefined
):
Initialize
current
with an empty object, so thecurrent().foo
will be parsed correctly (but its value beundefined
):
viewModel = new ViewModel(data);
viewModel.head();
viewModel.current({});
ko.applyBindings(viewModel);
您可以在绑定中添加一个额外条件,以检查current
是否具有某些值:
You can add an extra condition in your binding to check that current
has some value:
<input type="text" data-bind="value: current() && current().foo" />
或者最好和最推荐的选择是使用 with
绑定如果您要处理嵌套属性:
Or probably the best and most recommended option is to use the with
binding if you are dealing with nested proeprties:
<!-- ko with: current -->
<input type="text" data-bind="value: foo" />
<!-- /ko -->
演示 JSFiddle .
这篇关于带映射插件的Knockout.js工作流的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!