使用模块时如何在AngularJS中扩展或隔离常量值?

时间:2014-06-20 12:16:57

标签: angularjs constants modularity

为了保持我的代码清洁,我习惯在我的AngularJs应用程序中将url定义为常量,看起来像:

var myApp = angular.module('myApp', ['myModule']);
myApp.constant('URL', {
    google: 'http://www.google.com',
    facebook: 'http://www.facebook.com'
});

现在,这工作正常,但是当我在模块中定义(并使用)这个常量时,我​​遇到了问题:

var myModule= angular.module('myModule', []);
myModule.constant('URL', {
    twitter: 'http://www.twitter.com'
});

因为,现在当我想在指令(我的模块内)中使用URL.twitter常量时,它已不再可用,因为'myApp'中URL常量的定义已覆盖该值。例如,当我创建一个指令时:

myModule.directive('myDirective', function(){
    return {
        template: '<div></div>',
        controller: function(URL){
            console.log(URL.twitter); // logs undefined when used within 'myApp'
        }
    };
});

查看实时示例:http://plnkr.co/edit/xiOGVWfJ4GupSvkTs0Ic?p=preview

将'myModule'视为我在项目中包含的第三方模块。如果我不小心为常量使用相同的名称,那么整个事情就会被打破。

如何克服此用例而不必为同一目的使用不同的名称?

3 个答案:

答案 0 :(得分:4)

我认为这个问题归结为:

第三方模块(我没有写过)定义了&#39; URL&#39;作为常数。

我将此模块作为依赖项包含在我的应用中,并定义了URL(不知道该URL已经定义):

var app = angular.module('myApp', ['thirdPartyModule']);
app.constant('URL', { twitter: 'www.twitter.com'});

突然,应用程序崩溃并停止工作。

如何避免这个陷阱?

答案:

您可以使用角度注射器来确定是否已定义常量:

angular.module('myApp', ['thirdPartyModule']);
var injector = angular.injector(),
    url = injector.has('URL') ? injector.get('URL') : {};

上述代码将保证将返回一个对象 - 如果未定义,则返回第三方模块中定义的URL或空对象文字。

然后,您可以扩展&#39; URL&#39;如下:

angular.extend(url, { twitter: 'www.twitter.com' });

谨慎之词:

如果以前未定义URL或在第三方模块中将URL定义为对象文字,则此方法可行。如果先前将URL定义为基元(即字符串),则无效。

不幸的是,我无法想办法以干净的方式防范这种情况。我建议不要重写先前定义的常量,并依靠命名约定来使您的注射剂具有唯一性。例如,对于常量,服务,提供者和工厂,使用唯一的前缀来减少命名冲突的可能性:

var app = angular.module('tgApp', ['thirdPartyModule']);
app.constant('tgURL', { ... });

答案 1 :(得分:1)

我意识到这是一个老问题,但我没有看到这个答案。在OP所描述的同一个问题上,我花了几个小时把头撞在桌子上。我有很多jQuery小部件我正在转换为angular。这些基本上是将在多个站点中使用的第三方模块。我通过为每个模块使用提供程序解决了这个问题。

var myModule = angular.module('myModule', []);

myModule.provider('myModuleProvider', function() {
    this.$get = [function() {
        return {
            twitter: 'http://www.twitter.com',
        };
    }]
})

myModule.directive('myDirective', function() {
    return {
        template: '<div></div>',
        controller: function(myModuleProvider) {
            var URL = myModuleProvider;
            console.log(URL.twitter);
        }
    }
})

我的示例确实充分利用了提供程序,但好处是它们可以配置。因此,如果我有“选项”,我想公开它们可以通过myModule注入的模块上的angular.config()函数进行配置。

答案 2 :(得分:0)

您正在创建名为 myApp 的角度模块,该模块取决于模块 myModule
然后在模块 myApp

中添加一些常量
var myApp = angular.module('myApp', ['myModule']);
myApp.constant('URL', {
    google: 'http://www.google.com',
    facebook: 'http://www.facebook.com'
});

然后您正在创建 myModule 并将twitter常量添加到其中。那就是:
   - 谷歌和Facebook必须 myApp
   - twitter绑定到 myModule

然后,您将URL注入指令,尝试恢复Twitter URL。 这在很大程度上取决于myModule.directive行之前的内容。

使用:var myModule = angular.module('myModule')您应该找到 twitter 常数
使用:var myModule = angular.module('myApp')您应该找到 google facebook 常量


我通常使用更清晰的(在我看来)方法:

var myApp = angular.module('myApp')
myApp.factory('appConstants', function() {
    return {
        facebook: "www.facebook.com",
        google: "www.google.com",
        twitter: "www.twitter.com"
    }   
})

然后您只需在需要时将其注入并使用它:appConstants.facebook

你怎么看?