在没有订阅触发的情况下设置knockout.js observable

时间:2012-07-01 14:23:34

标签: javascript knockout.js

如何设置一个可观察的属性,而不会为其触发任何订阅?

我有一个场景是页面加载,进行ajax调用以获取一些数据,数据循环,然后将当前选择的项目设置为observable。我希望能够设置这个observable,而不会触发任何订阅,因为第一次设置这个observable被认为是它的初始状态,订阅不应该在初始状态下执行。

function PlanViewModel() {
    var self = this;

    self.plans = ko.observableArray();
    self.selectedItem = ko.observable();

    self.getAllPlans = function () {
        $.ajax({
            url: "/Backoffice/Home/GetAllPlans",
            type: "POST",
            data: {},
            context: this,
            success: function (result) {
                var planList = this.plans;
                // clear the plan list
                planList.removeAll();
                $.each(result.plans, function () {
                    var planDetail = new PlanDetail(this, self);
                    if (this.IsSelected) {
                        self.selectedItem(planDetail); // how do I set this without the subscriptions firing?
                    }
                    planList.push(planDetail);
                });
            },
            error: function (result) {
                alert("An error occured getting plans.");
            }
        });
    }

    self.selectedItem.subscribe(function (newItem) {
        newItem.repositoryUpdateSelectedPlan();
    } .bind(self));
}

2 个答案:

答案 0 :(得分:4)

您可以像这样重构代码:

function PlanViewModel() {
    var self = this;

    self.plans = ko.observableArray();

    self.getAllPlans = function () {
        $.ajax({
            // …
            success: function (result) {
                // …
                $.each(result.plans, function () {
                    var planDetail = new PlanDetail(this, self);
                    if (this.IsSelected) {
                        self.selectedItem = ko.observable(planDetail);
                    }
                    planList.push(planDetail);
                });
                if (self.selectedItem === undefined) { 
                    self.selectedItem = ko.observable(); 
                }
                self.selectedItem.subscribe(function (newItem) {
                    newItem.repositoryUpdateSelectedPlan();
                }.bind(self));
            },
            // …
        });
    }
}

也就是说,只有在达到所需的初始状态后才能启动Knockout

答案 1 :(得分:-1)

谢谢,我沿着那条路走下去并进行了一些修改。必须在get go中在模型上定义selectedItem observable,因为它在整个地方用于绑定,但我确实像你建议的那样移动了订阅部分,而且效果很好。

function PlanViewModel() {
    var self = this;

    var selectedItemSubscription = null;

    self.plans = ko.observableArray();
    self.selectedItem = ko.observable();

    self.getAllPlans = function () {
        $.ajax({
            url: "/Backoffice/Home/GetAllPlans",
            type: "POST",
            data: {},
            context: this,
            success: function (result) {
                var planList = this.plans;
                // clear the plan list
                planList.removeAll();
                $.each(result.plans, function () {
                    var planDetail = new PlanDetail(this, self);
                    if (this.IsSelected) {
                        if (selectedItemSubscription != null)
                            selectedItemSubscription.dispose();

                        self.selectedItem(planDetail);
                    }
                    planList.push(planDetail);
                });

                selectedItemSubscription = self.selectedItem.subscribe(function (newItem) {
                    newItem.repositoryUpdateSelectedPlan();
                }.bind(self));
            },
            error: function (result) {
                alert("An error occured getting plans.");
            }
        });
    }
}