3

我正在尝试将 jqplot 与 Durandal 和淘汰赛一起使用。我在 Durandal 组 ( https://groups.google.com/forum/#!topic/durandaljs/WXBiSK3WmIs ) 上找到了 Rob 的帖子,该帖子解决了这个问题,但它使用的视图模型结构完全让我感到困惑向构造函数添加“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 没有触发。此视图模型是主页面中的子视图。不知道这是否会影响事情?

我的视图模型现在是:

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;

    });
4

2 回答 2

5

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

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

此示例视图模型返回一个函数,而不是单例:

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

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

  return example;
});

此视图模型返回一个单例,并需要前一个作为依赖项:

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

由于 'viewmodels/example' 返回一个函数,我们必须使用new关键字来实例化它(注意:如果您在视图中使用组合绑定,Durandal 将为您执行此操作)。

两者exampleOne都有exampleTwo独特的头衔;但是,它们共享相同的activate()方法。这就是prototype物业的优势。此策略可以应用于您想要复制的视图,但共享相同的激活代码,例如模式对话框或小部件。

于 2013-11-07T21:25:16.343 回答
0

好吧,在没有更多学习的解决方案的情况下,我至少设法让它发挥作用。我不得不删除 ctor 函数并使其成为一个普通的页面变量。必须删除对“self”的所有引用,因为在最后一个 durandal 事件中,“this”不是 window 对象。

由于“compositionComplete 没有在我的视图模型中触发,因此我使用了“附加”。

工作代码:

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;

    });
于 2013-11-07T17:22:58.050 回答