durandal激活器 - 如何在加载或首次使用时创建一个实现activate()的模块

时间:2014-04-01 18:15:12

标签: durandal activator

在阅读有关激活剂的文档后,我仍然对如何使用激活剂感到困惑。我想做的很简单:

我已经定义了一个名为global的requireJS模块。当我在其他模块中使用此模块时,不会调用它的激活功能。我需要它。

如果我使用compose:加载模块,激活函数就可以了。但是,如果我只是将它作为AMD模块加载,他们就不会。这就是我想解决的问题。

注意:我的模块是一个单独的,我只需要激活才能实际运行一次,所以我尝试了类似这样的东西,它不起作用,我的shell.js

define(['plugins/router', 'durandal/app', 'plugins/ajax','durandal/global'], function (router, app,ajax,global) {

    var vm = {};

    vm.global = global;

    vm.activate= function () {
        return vm.rebuildRouter();

//not sure what this does, does it return a promise, does it run global's activate, does it hook up global so it activates at a later time, and if so when?
        global.activator.activateItem(global); //I created an activator and called in activator inside global. Since its a singlton I think I only need one?

//Since I wasn't sure how to use activators I had to do this instead:
    var promise = global.activate();
        return promise;

//which works only the first time 
    }

如果有人可以向我解释这个激活业务,我会很感激。我一直使用激活compose,并且按照我想要的方式工作。我只是不明白我需要做些什么才能让它按上述方式工作,并且无法找到一个简单的例子来说明如何让任何js模块以相同的方式运行。

3 个答案:

答案 0 :(得分:3)

activator是一个特殊的计算的obseravble ,当其值尝试更改时,其写入函数会强制执行activation lifecycle

激活生命周期

  1. canDeactivate在当前值
  2. 上调用 在尝试设置的值上调用
  3. canActivate
  4. deactivate在当前值
  5. 上调用 在尝试设置的值上调用
  6. activate

    使用激活器强制某些对象在其值发生变化时触发这些事件,并在canDeactivatecanActivate返回false时阻止更改。

    听起来你不想要一个激活剂。您没有尝试根据这些规则强制执行值更改,您正在尝试确保模块在使用之前执行某些逻辑。它只需要执行一次这个逻辑,因为它是一个单例。

    不幸的是,RequireJS没有提供等待模块执行异步工作的方法(我知道)。

    这是你可以做的一件事。由于Durandal的app.start初始化是一个异步过程,您可以将其挂钩,以便在setRoot初始化之后调用global

    全局文件

    define(['durandal/app', 'plugins/ajax', 'durandal/global'], function (app,ajax) {
        return function GlobalModule() {
            activate: function() {
                return //some promise;
            }
        };
    });
    

    Main.js

    define(['durandal/system', 'durandal/app', 'durandal/global'],
    function (system, app, global) {
        app.configurePlugins({ /* plugins */ });
    
        app.title = 'App';
        app.start()
            .then(global.activate)
            .then(function () {
                app.setRoot('shell');
            });
    });
    

    这将确保setRootglobal完成激活之前不会启动。然后,在您的任何应用代码中使用它都应该是安全的。

    请记住,我不知道durandal/global是什么,这项工作取决于activate是一个承诺返回功能。

答案 1 :(得分:2)

你的问题中有许多不正确的假设...你正在混淆AMD模块解析(由require.js完成)和视图合成(一个durandal概念),好像它们是相同的东西。

无论如何,我认为你在这里与激活者走错了路(因为它们与简单的AMD模块分辨率是一个单独的概念)所以我要回避实际问题,并回答我认为你的问题应该是,如何将自动初始化逻辑添加到AMD模块?

鉴于您只希望初始化发生一次,那就告诉我您还希望模块是单例。

无论哪种方式,我都认为实现初始化逻辑没有比模块的构造函数更精细的地方。

基本上你想要将AMD模块作为构造函数实现,将你的init逻辑放在那里,并利用单例模式,这样初始化逻辑只发生一次。

这对您来说可能是一个有用的资源:

http://unscriptable.com/2011/09/22/amd-module-patterns-singleton/

如果我错过了你在这里尝试做的事情,请道歉。

答案 2 :(得分:0)

我最终完成了我所需要的,但这是最好的方式和/或如何做到这一点?我认为这不是理想的,因为我需要在每个模块中使用所有这些代码,包括我所包含的每个模块:

var viewModel = {};     viewModel.global = activator.create();

viewModel.activate = function () {

    return $.when(viewModel.global.activateItem(global),
               ... other ajax calls and stuff
               ))
               .then(function () {
                    //stuff I used to have in my activate function before, that needs global to already exist
               });
};

这真的是如何正确使用激活剂吗?我上面的工作,但正如有人指出我可以调用global.activate()而不是activateItem(全局),我根本不需要激活器..那么,目的是什么它?

当你撰写某些东西时,激活生命周期就会自行发生。我正在尝试构建一个具有生命周期的模块,即使我没有编写它,这可能吗?