【问题标题】:Durandal and Knockout difference between activate method and ctor.prototype.activate?激活方法和ctor.prototype.activate之间的Durandal和Knockout区别?
【发布时间】:2013-11-19 07:39:26
【问题描述】:

我正在尝试将 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;

    });

【问题讨论】:

  • 从 Durandal 的角度来看,这两种方法应该是一样的。因此,如果您将所有内容都放入您的 activate 函数中,您的代码应该可以工作,以便进一步帮助您发布您的实际代码,哪些是不工作的......
  • 啊。我明白你的意思了。我遇到的问题是var ctor=function()... 位,因为它位于逻辑之外并且在调用我的激活函数时未初始化。在尝试将数据推送到对象之前,我是否只需要将 ctor(); 作为激活方法的第一行?
  • 已编辑 OP。 compositionComplete 没有触发。

标签: javascript knockout.js durandal


【解决方案1】:

您必须了解返回单例视图模型和函数视图模型之间的根本区别。您还需要了解继承在 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 将为您执行此操作。

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

【讨论】:

  • 感谢布雷特的解释。我可以理解为类似于.net“类”系统,其中“新”对象可以实例化为同一类的实例,但每个实例中具有唯一值。我认为我正在努力解决的是函数/构造函数版本很有用的现实情况!我会继续阅读它,看看我是否能找到一些东西,但如果你知道任何在线资源是一个很好的例子,我非常感谢你指点我!
  • 使用此模式的一个很好的例子是使用提供的dialog 插件在 Durandal 中创建自定义对话框。请参阅http://durandaljs.com/documentation/Showing-Message-Boxes-And-Modals/,然后向下滚动到“自定义对话框”部分。看看 MessageBox 是如何实现的——它使用了函数模式。
【解决方案2】:

好吧,在没有更多学习解决方案的情况下,我至少设法让它发挥作用。我不得不删除 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;

    });

【讨论】:

    猜你喜欢
    • 2023-03-12
    • 1970-01-01
    • 2021-07-15
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-21
    • 2013-01-30
    相关资源
    最近更新 更多