激活方法和ctor.prototype.activate之间的Durandal和Knockout区别?

时间:2013-11-07 15:20:32

标签: javascript knockout.js durandal

我正在尝试将jqplot与Durandal和淘汰赛一起使用。我发现Rob在Durandal组(https://groups.google.com/forum/#!topic/durandaljs/WXBiSK3WmIs)上发布了一篇解决这个问题的帖子,但它使用了一个构造用于viewmodel,它完全混淆了我,因为它为构造函数添加了一个“prototype.activate”方法,这完全是对我来说是新的(当我尝试使用它时不起作用)。

任何人都可以试着告诉我如何使用我的揭示模块模式使用Rob的示例如下所示?

我的观点模型:

define(['globalVar', 'services/datacontext', 'services/calccontext"], function (globalVar, datacontext, calcContext) {


        var activate = function () {
            return datacontext.newEntity(articleResults, "articleVersionResults");
        };

        var calcAll = function () {
            //can be called externally and recalcs all
            return individualImpactCalc('byWeightAndFactor', 'CO2e', articleResults().material_CO2e);
           //will be more calls in here soon
        };

        var individualImpactCalc = function (calcName, fac, calcObservable) {
            return calcContext.indCalc(calcName, fac, calcObservable, globalVar.components()); //puts result straight into observable
        };

        var vm = {
            activate: activate,
            calcAll: calcAll
        };

        return vm;
    });

Rob的代码示例:

define(["jquery", "knockout"], function($, ko){
  // constructor
  var ctor = function () {
    var self = this;

    // properties
    self.chartConfig = {};
  };

ctor.prototype.activate = function(id, page) {
    var self = this;

    // get data from database
    self.chartConfig.data([
        [300, 295, 290],
        [320, 320, 320],
        [260, 265, 260]
    ]);
    self.chartConfig.title("Forecast net operating costs");
    self.chartConfig.seriesColors(["#0026FF", "#FF6A00", "#606060"]);
    self.chartConfig.series([
        { label: "Foo" },
        { label: "Bar" },
        { label: "Baz" }
    ]);
    self.chartConfig.ticks(["Apr 13", "May 13", "Jun 13"]);
};

ctor.prototype.compositionComplete = function (view, parent) {
    var self = this;
    var c = self.chartConfig;

    self.jqChart = $.jqplot("chart", c.data(), ...

    // example to change the data
    setTimeout(function () {
        self.chartConfig.data([
            [280, 280, 280],
            [280, 280, 280],
            [280, 280, 280]
        ]);
    }, 4000);
};


  return ctor;
});

编辑1: 问题是compositioncomplete没有触发。此视图模型是主页面中的子视图。不知道这是否会影响事情?

我的viewmodel现在是:

define(['globalVar', 'services/datacontext', 'services/calccontext', "jquery", "knockout"], function (globalVar, datacontext, calcContext, $, ko) {


    // constructor
        var ctor = function () {
            var self = this;

            // properties
            self.chartConfig = {
                data: ko.observableArray([]),
                title: ko.observable(),
                seriesColors: ko.observableArray([]),
                series: ko.observableArray([]),
                ticks: ko.observableArray([])
            };

            // subscriptions
            self.chartConfig.data.subscribe(function (newValue) {
                var opts = {
                    data: newValue
                };
                if (self.jqChart) {
                    self.jqChart.replot(opts);
                    console.log("chart replotted", opts);
                }
            });
        };

        function setChartVars() {
            var self = this;

            // get data from database
            self.chartConfig.data([
                [300, 295, 290],
                [320, 320, 320],
                [260, 265, 260]
            ]);
            self.chartConfig.title("Forecast net operating costs");
            self.chartConfig.seriesColors(["#0026FF", "#FF6A00", "#606060"]);
            self.chartConfig.series([
                { label: "Foo" },
                { label: "Bar" },
                { label: "Baz" }
            ]);
            self.chartConfig.ticks(["Apr 13", "May 13", "Jun 13"]);
        };

        var activate = function () {
            ctor();
            setChartVars();
            return datacontext.newEntity(articleResults, "articleVersionResults");
        };

        var compositionComplete = function () {
            var self = this;
            var c = self.chartConfig;

            self.jqChart = $.jqplot("chart", c.data());

            // example to change the data
            setTimeout(function () {
                self.chartConfig.data([
                    [280, 280, 280],
                    [280, 280, 280],
                    [280, 280, 280]
                ]);
            }, 4000);
        };

        var calcAll = function () {
            //can be called externally and recalcs all
            //return res_mat_gwp();
            return individualImpactCalc('byWeightAndFactor', 'CO2e', articleResults().material_CO2e);
        };

        var individualImpactCalc = function (calcName, fac, calcObservable) {
            return calcContext.indCalc(calcName, fac, calcObservable, globalVar.components()); //puts result straight into observable
        };

        var vm = {
            activate: activate,
            compositionComplete: compositionComplete,
            calcAll: calcAll,
            editArticleVersion: globalVar.editArticleVersion,
            articleResults: articleResults,
            ctor: ctor
        };

        return vm;

    });

2 个答案:

答案 0 :(得分:5)

您必须了解返回单例视图模型和函数视图模型之间的根本区别。您还需要了解继承如何在JavaScript中工作以掌握prototype属性背后的目的以及为何使用它。

您已经了解了单例视图模型 - 这就是您一直在构建视图模型的方式,因此,您最熟悉它。另一种方法,你不太了解,是一种将“接口”返回到视图模型的方法,目的是实例化它们中的一个或多个。如果您将viewmodel作为函数返回,则必须使用new关键字来实例化它。让我用一个例子来说明这一点。

此示例viewmodel返回一个函数,而不是单例:

define([], function () {
  var example = function (title) {
    this.title = title;
  };

  example.prototype.activate = function (params) {
    // do something with the params
  };

  return example;
});

此viewmodel返回一个单例,并要求前一个作为依赖项:

define(['viewmodels/example'], function (Example) {
  return {
    exampleOne: new Example('This is a test!'),
    exampleTwo: new Example('This is another test!')
  };
});

由于'viewmodels / example'返回一个函数,我们必须使用new关键字来实例化它(注意:如果你在视图中使用合成绑定,Durandal会为你做这个。)

exampleOneexampleTwo都有独特的标题;但是,它们共享相同的activate()方法。这是prototype属性的优势。此策略可应用于您想要复制的视图,但共享相同的激活码,如模态对话框或小部件。

答案 1 :(得分:0)

好吧,在没有更多学习解决方案的情况下,我至少设法让它运转起来。我不得不删除ctor函数并使其成为普通页面变量。不得不删除所有对“self”的引用,就像在最后一个durandal事件中那样“this”不是窗口对象。

由于“compositionComplete未在我的viewmodel中触发,我使用”附加“代替。

工作代码:

define(['globalVar', 'services/datacontext', 'services/calccontext', "jquery", "knockout"], function (globalVar, datacontext, calcContext, $, ko) {

    var chartConfig = {
        data: ko.observableArray([]),
        title: ko.observable(),
        seriesColors: ko.observableArray([]),
        series: ko.observableArray([]),
        ticks: ko.observableArray([])
    };

    // subscriptions
    chartConfig.data.subscribe(function (newValue) {
        var opts = {
            data: newValue
        };
        if (self.jqChart) {
            self.jqChart.replot(opts);
            console.log("chart replotted", opts);
        }
    });

        function setChartVars() {
            //var self = this;

            // get data from database
            chartConfig.data([
                [300, 295, 290],
                [320, 320, 320],
                [260, 265, 260]
            ]);
            chartConfig.title("Forecast net operating costs");
            chartConfig.seriesColors(["#0026FF", "#FF6A00", "#606060"]);
            chartConfig.series([
                { label: "Foo" },
                { label: "Bar" },
                { label: "Baz" }
            ]);
            chartConfig.ticks(["Apr 13", "May 13", "Jun 13"]);
        };

        var activate = function () {
            setChartVars();
            return datacontext.newEntity(articleResults, "articleVersionResults");


        };

        var compositionComplete = function () {
            //var self = this;
            var c = chartConfig;

            jqChart = $.jqplot("chart", c.data());

            // example to change the data
            setTimeout(function () {
                chartConfig.data([
                    [280, 280, 280],
                    [280, 280, 280],
                    [280, 280, 280]
                ]);
            }, 4000);
        };

        var calcAll = function () {
            //can be called externally and recalcs all
            //return res_mat_gwp();
            return individualImpactCalc('byWeightAndFactor', 'CO2e', articleResults().material_CO2e);
        };

        var individualImpactCalc = function (calcName, fac, calcObservable) {
            return calcContext.indCalc(calcName, fac, calcObservable, globalVar.components()); //puts result straight into observable
        };

        var vm = {
            activate: activate,
            attached: compositionComplete,
            calcAll: calcAll,
            editArticleVersion: globalVar.editArticleVersion,
            articleResults: articleResults
        };

        return vm;

    });