AngularJS:处理全局变量的最佳方法($rootScope或全局服务?)

AngularJS:处理全局变量的最佳方法($rootScope或全局服务?),angularjs,Angularjs,我在使用$rootScope和全局服务之间左右为难 $rootScope让人感觉脏兮兮的,而且还带来了所有全局变量的问题,所以我想使用全局服务,但Angular FAQ说: 当然,全局状态很糟糕,您应该节约使用$rootScope, 就像您(希望)在任何语言中使用全局变量一样。 特别是,不要将其用于代码,只用于数据。如果你想 将函数放在$rootScope上,将其放在 可以在需要的地方注入服务,而且更容易 测试 相反,不要创建一个服务,它在生活中的唯一目的就是 存储和返回数据位 …这就是我想使用

我在使用$rootScope和全局服务之间左右为难

$rootScope让人感觉脏兮兮的,而且还带来了所有全局变量的问题,所以我想使用全局服务,但Angular FAQ说:

当然,全局状态很糟糕,您应该节约使用$rootScope, 就像您(希望)在任何语言中使用全局变量一样。 特别是,不要将其用于代码,只用于数据。如果你想 将函数放在$rootScope上,将其放在 可以在需要的地方注入服务,而且更容易 测试

相反,不要创建一个服务,它在生活中的唯一目的就是 存储和返回数据位

…这就是我想使用这项服务的目的

例如,我有一个导航栏,当在移动屏幕上切换时,应该向body和html元素添加一个类。我用指令和控制器来处理这个问题

导航控制器:

function NavbarController($rootScope) {
    var vm = this;
    vm.toggleNav = toggleNav;
    $rootScope.navCollapsed = false;

    function toggleNav() {
        $rootScope.navCollapsed = !$rootScope.navCollapsed;
    }
}
function NavbarController(globalService) {
    var vm = this;
    vm.toggleNav = toggleNav;
    globalService.navCollapsed = false;

    function toggleNav() {
        globalService.navCollapsed = !globalService.navCollapsed;
    }
}
如您所见,我将rootScope用于navCollapsed值,在我的指令中,我这样做:

function navOpen($rootScope) {
    return {
        restrict: 'A',
        link: function(scope, element) {
            scope.$watch(function () {
                return $rootScope.navCollapsed;
            }, function () {
                if ($rootScope.navCollapsed)
                    element.addClass('nav-open');
                else
                    element.removeClass('nav-open');
            });
        }
    };
}
它工作得很好,但使用$rootScope感觉很脏。我宁愿做这样的事情:

导航控制器:

function NavbarController($rootScope) {
    var vm = this;
    vm.toggleNav = toggleNav;
    $rootScope.navCollapsed = false;

    function toggleNav() {
        $rootScope.navCollapsed = !$rootScope.navCollapsed;
    }
}
function NavbarController(globalService) {
    var vm = this;
    vm.toggleNav = toggleNav;
    globalService.navCollapsed = false;

    function toggleNav() {
        globalService.navCollapsed = !globalService.navCollapsed;
    }
}
在指令中:

function navOpen(globalService) {
    return {
        restrict: 'A',
        link: function(scope, element) {
            scope.$watch(function () {
                return globalService.navCollapsed;
            }, function () {
                if (globalService.navCollapsed)
                    element.addClass('nav-open');
                else
                    element.removeClass('nav-open');
            });
        }
    };
}
它的作用完全相同,只是现在值在一个位置,不能在其他地方无意中更改,这更好,但根据AngularJS团队的说法,这是一种不好的做法,因为它是“数据位”


最好的方法是什么?我还有其他具有类似功能的变量需要是全局变量(可以在任何控制器中访问以进行操作),而不必使用$rootScope。

为什么要将导航栏的状态存储在全局服务或rootScope中?为什么不将其存储在导航栏控制器的范围内?没有人需要那种状态,对吗?这就是它的归属。你的指令也没用。您所需要的只是navbar模板中的ng类来添加/删除CSS类。CSS类用于body/html标记,navbar包含在我的状态中的ng include中,因此它具有不同的作用域。单击导航栏切换时,应将nav open类添加到html/body标记中。这就是为什么我要使用一个指令(我仍然可以使用带有rootscope变量的ng类,但我更喜欢使用一个指令来保持html的整洁)——不管怎样,我仍然必须使用rootscope,这样我就可以访问html/body标记上的值,而不是navbar。除非有别的办法……你是在重新发明轮子。当标准指令执行您需要执行的任务时,请使用标准指令。如果控制器应该驱动body元素的状态,那么在body元素上使用它。虽然我不明白为什么需要在主体上设置CSS类来打开导航栏。顺便说一句,您的代码没有这样做:它在navbar指令元素上设置CSS类。“nav open”指令位于html/body标记上,而不是位于navbar上。我没有使用bootstrap中的默认导航栏,我自己制作了一个,因此body/html幻灯片和导航栏来自左侧(这是用于移动屏幕)。使用jquery很容易,但我不能使用jquery,因为navbar还没有加载到DOM中,所以它不工作,这也是我使用指令的另一个原因。您可以简单地在主控制器中使用并执行此操作。但是,如果您确实想使用服务,因为您需要从两个单独的代码图片访问/控制导航栏,那么请定义导航栏服务,并在该服务中公开toggle()和isOpened()方法。不要为此使用rootScope。为什么要将导航栏的状态存储在全局服务或rootScope中?为什么不将其存储在导航栏控制器的范围内?没有人需要那种状态,对吗?这就是它的归属。你的指令也没用。您所需要的只是navbar模板中的ng类来添加/删除CSS类。CSS类用于body/html标记,navbar包含在我的状态中的ng include中,因此它具有不同的作用域。单击导航栏切换时,应将nav open类添加到html/body标记中。这就是为什么我要使用一个指令(我仍然可以使用带有rootscope变量的ng类,但我更喜欢使用一个指令来保持html的整洁)——不管怎样,我仍然必须使用rootscope,这样我就可以访问html/body标记上的值,而不是navbar。除非有别的办法……你是在重新发明轮子。当标准指令执行您需要执行的任务时,请使用标准指令。如果控制器应该驱动body元素的状态,那么在body元素上使用它。虽然我不明白为什么需要在主体上设置CSS类来打开导航栏。顺便说一句,您的代码没有这样做:它在navbar指令元素上设置CSS类。“nav open”指令位于html/body标记上,而不是位于navbar上。我没有使用bootstrap中的默认导航栏,我自己制作了一个,因此body/html幻灯片和导航栏来自左侧(这是用于移动屏幕)。使用jquery很容易,但我不能使用jquery,因为navbar还没有加载到DOM中,所以它不工作,这也是我使用指令的另一个原因。您可以简单地在主控制器中使用并执行此操作。但是,如果您确实想使用服务,因为您需要从两个单独的代码图片访问/控制导航栏,那么请定义导航栏服务,并在该服务中公开toggle()和isOpened()方法。不要为此使用rootScope。