Knockout.js:无法解析JSON的绑定

reb*_*ion 2 ajax jquery json knockout-2.0 knockout.js

我有一个通过AJAX获取JSON的视图模型,并创建一个新的Task,但Knockout继续给我一个绑定错误.

如果我在视图模型中直接硬编码来自服务器的数据,我不会收到任何错误.

我的视图模型创建了新任务,它有一个id,一个问题和一些替换,它们本身有一个文本和正确的布尔标志.

以下代码完美无缺:

function Task(data) {
    var self = this;

    self.id = data.id;
    self.question = ko.observable(data.question);

    var alts = new Array();
    $(data.alternatives).each(function(index){
        alts.push(new Alternative(data.alternatives[index].alternative, data.alternatives[index].correct));
    });

    self.alternatives = ko.observableArray(alts);
}
function Alternative(alternativeText, correctAnswer) {
    var self         = this;
    self.alternative = ko.observable(alternativeText);
    self.correct     = ko.observable(correctAnswer);
}
function TaskViewModel() {
    var self = this;

    var data = {
        id: 5,
        question: 'test',
        alternatives: [{
            alternative: 'alt 1',
            correct: false
        },{
            alternative: 'alt 2',
            correct: true
        },{
            alternative: 'alt 3',
            correct: false
        }]
    };

    self.task = new Task(data);
}
Run Code Online (Sandbox Code Playgroud)

但是如果我data用来自服务器的真实数据来解析硬编码变量:

function TaskViewModel() {
    var self = this;

    $.getJSON('/data', function(data){
        self.task = new Task(data);
    });
}
Run Code Online (Sandbox Code Playgroud)

Knockout给了我这个错误:

Error: Unable to parse bindings.
Message: ReferenceError: Can't find variable: task;
Bindings value: value: task.question
Run Code Online (Sandbox Code Playgroud)

来自URL的数据如下所示:

{"id":5,"question":"test","alternatives":[{"alternative":"alt 1","correct":false},{"alternative":"alt 2","correct":true},{"alternative":"alt 3","correct":false}]}
Run Code Online (Sandbox Code Playgroud)

我似乎无法弄清楚为什么这不起作用:/

Jef*_*ado 6

task在应用绑定时,您的视图模型实际上没有属性.你需要给它一些东西来绑定.

有几种方法可以解决这个问题.

可能最简单的方法是使taskobservable并将其设置为ajax调用的结果.您可能需要调整绑定以考虑此更改.

function TaskViewModel() {
    var self = this;
    self.task = ko.observable();

    $.getJSON('/data', function(data){
        self.task(new Task(data));
    });
}
Run Code Online (Sandbox Code Playgroud)

更灵活的选择是为Task对象添加单独的初始化方法并设置任务(未初始化).然后作为ajax调用的结果,调用初始化方法来初始化它.当然,您必须调整任务对象的初始化代码.

function TaskViewModel() {
    var self = this;
    self.task = new Task();

    $.getJSON('/data', function(data){
        self.task.init(data);
    });
}

function Task() {
    var self = this;
    self.id = ko.observable();
    self.question = ko.observable();
    self.alternatives = ko.observableArray();

    self.init = function (data) {
        self.id(data.id);
        self.question(data.question);
        self.alternatives(ko.utils.arrayForEach(data.alternatives, function (item) {
            return new Alternative(item.alternative, item.correct);
        }));
    };
}
Run Code Online (Sandbox Code Playgroud)