【问题标题】:Angularjs - $rootScope in directive link functionAngularjs - 指令链接函数中的 $rootScope
【发布时间】:2014-03-11 07:16:50
【问题描述】:

我问这个问题是因为我不太清楚如何将 rootscope 视为传递给指令的依赖项

我有一个指令需要显示来自 $rootScope 的一些信息 ...

我认为我需要将 $rootScope 传递给指令,但是当我编写这样的指令时,它似乎可以工作。

.directive("myBar", function () {
 return {
    restrict: "E",
    transclude: true,
    replace: true,
    template:   '<div>' + 
                '<span ng-transclude></span>' + 
                '{{rsLabels.welcome}} {{rsUser.firstName}}!' + 
                '</div>'
}
})

我什么时候需要这样做?

.directive("myBar", function ($rootScope) {
 return {
    restrict: "E",
    transclude: true,
    replace: true,
    template:   '<div>' + 
                '<span ng-transclude></span>' + 
                '{{rsLabels.welcome}} {{rsUser.firstName}}!' + 
                '</div>'
}
})

如果我需要在指令的链接函数中使用 rootScope,我可以以及如何使用它 - 还是应该在指令的控制器中使用它?

.directive("myBar", function ($rootScope) {
 return {
    restrict: "E",
    transclude: true,
    replace: true,
    link: function (scope, element, attrs, rootScope) {
        rootScope.rsUser = { firstName: 'Joe' };
        rootScope.rsUser = { welcome: 'Welcome' };
    },
    template:   '<div>' + 
                '<span ng-transclude></span>' + 
                '{{rsLabels.welcome}} {{rsUser.firstName}}!' + 
                '</div>'
}
})

我的 rootScope 数据是在 run 函数中定义的

 .run(function ($rootScope) {

  $rootScope.rsLabels = { 
      welcome: 'Welcome'
  };

  $rootScope.rsUser = { 
     firstName: 'Joe'
  };
});

谢谢!

【问题讨论】:

    标签: angularjs angularjs-directive angularjs-scope rootscope


    【解决方案1】:

    不建议使用根范围来设置和获取 Angular 应用程序中的属性。尝试使用 $cacheFactory,因为这样您还可以在各种请求中缓存一些值。 ($cacheFactory docs)

    【讨论】:

    • 是的,我认为像这样使用 $rootScope 并不是最好的主意。谢谢你的建议。我正在寻找更好的方法来创建可广泛访问的对象,尽管我可以从各种指令中使用站点范围内的对象。我发现 Angular 网站上的文档完全没用(就像该网站的大部分内容一样),因为它既没有解释任何东西,也没有展示真实的用例或至少是逻辑用例。在我的情况下,整个站点的所有指令都必须始终能够访问用户信息、和其他一些信息。最好的办法?你知道有用吗。好的文档可能吗?
    • 嘿,我发现了一些很好的信息,加上这个jmdobry.github.io/angular-cache/guide.html,还有一个有用的 YT 视频..感谢这个提示!我非常感谢 :) 我想我会更深入地研究它作为我正在研究的实际使用方法。然而,迈克确实用解释解决了我的问题,所以我会将他的答案标记为正确答案。
    【解决方案2】:

    根据我的实验\经验,似乎由于所有 $scopes 最终都从 $rootScope 继承,您将能够访问其上的数据,而无需将其作为服务请求,遵循标准的 javascript 原型继承规则。如果您将指令中的范围属性设置为 false 或 {},您会发现您无法再访问它。

    .directive("myBar", function($rootScope) {
        return {
            restrict: "E",
            scope: { /* Isolate scope, no $rootScope access anymore */ },
            transclude: true,
            replace: true,
            template: '<div>' + 
                      '<span ng-transclude></span>' + 
                      '{{rsLabels.welcome}} {{rsUser.firstName}}!' + 
                      '</div>'
        };
    });
    

    示例:http://jsbin.com/bequy/1/edit

    【讨论】:

    • 啊!我明白。正如 Kurt 指出的那样,这不是以角度设置应用程序属性的最佳方式,但我需要了解 rootScope,这可以更好地解释它。谢谢你。你不知道如何在指令的链接函数中访问 $root 范围吗?
    • 您需要将 $rootScope 视为全局命名空间,并且您希望避免将其弄乱。你可以在你的指令中注入它,但指令的全部意义在于成为一个没有太多外部依赖的组件。如果您需要 $rootScope 中的某些内容,您可以考虑将其重构为服务。
    • 有道理。我想我正在诉诸于使用任何与全局变量等效的 kin dof,因为必须始终使数据 x 可用并且不知道如何处理它。我确实将 localStorage 用于某些东西,但现在查看 cacheFactory 及其扩展版本,以及他们如何使用 localstorage,我看到了曙光。谢谢!
    • 设置范围:true 将使其工作。通过将其设置为空哈希 {} 或 false 来隔离范围并中断继承链。 (请参阅指令定义对象,范围)code.angularjs.org/1.4.1/docs/api/ng/service/$compile(我的示例针对 1.2.1,但与我所知的情况相比并没有改变)。
    【解决方案3】:

    你可以这样做:

    {{$root.rsLabels.welcome}}
    

    【讨论】:

    • 谢谢,不是这样。我使用link: function(scope, ...) { scope.$root } 从指令访问$rootScope
    • 是的,我的意思是我在谷歌上搜索从指令访问 $rootScope 而我不知道 $root 属性。感谢您的回答。
    • 应该是正确的答案...谢谢,无论如何提供您的解决方案。
    • 固体溶液。 A+
    【解决方案4】:

    在同一个问题上苦苦思索了很长一段时间后,我认为值得注意的是在第一篇文章中被忽略的一些内容。这是我的原始代码:

    app.directive('countrymap', function() 
    {
        return {
            link: function(scope, element, attrs) {
                scope.$watch("countryMap", function (newCountry, oldCountry) 
                {
                    setTimeout( function() 
                    {
                        //function body here    
                    }, 100);
                })
            }
        };  
    }]);
    

    除了你是否应该使用 $rootScope 的更哲学的设计问题之外,我觉得上面的代码有一个明显错误的地方,我觉得 Mike 的解决方案忽略了 - 对 $rootScope 的引用。如果你和我一样并且已经分离了你的指令和控制器文件,你需要修改你的代码如下:

    app.directive('countrymap', ['$rootScope', function($rootScope) 
    {
        return {
            link: function(scope, element, attrs) {
                $rootScope.$watch("countryMap", function (newCountry, oldCountry) 
                {
                    setTimeout( function() 
                    { 
                        //function body here
                    }, 100);
                })
            }
        };  
    }]);
    

    然而,还有一个烦人的问题:我是否可以在在指令中引用$rootScope 的情况下实现相同的目标?确实可以。您需要有效地将更改广播到 $rootScope 属性,让所有子范围都知道更改并在指令中监视此更改。

    控制器:

    $rootScope.countryMap = 'thiscountry_map';
    $rootScope.$broadcast( "countryMapChanged", $rootScope.countryMap );
    

    指令:

    app.directive('countrymapalt', [function() 
    {
        return {
            link: function(scope, element, attrs) {
                scope.$on("countryMapChanged", function(event, map) 
                {
                    setTimeout( function() 
                    { 
                        //function body here
                    }, 100);
                })
            }
        };  
    }]);
    

    【讨论】:

      【解决方案5】:

      另一种方法是创建一个服务并让该服务访问 $rootScope 和其他功能。由于我的环境,我这样做了......

      app.service('myService', function ($rootScope) 
      {
          this.removeItem = function (el) 
          {
             console.log('rootScope: ',$rootScope);
             return true;
          }
      });
      
      
      app.directive('draggable', function($document,myService) 
      {
         return function(scope, element, attr) 
         {
              myService.removeItem({id:1})
         }
      });
      

      如果可以,最好的方法是迈克解决方案。 如果没有,请尝试我的解决方案。

      【讨论】:

        【解决方案6】:

        有时我必须使用 $scope.$root:

        app.directive('setOrdinal', function() {
          return {
            link: function($scope, $element, $attr) {
        
              var steps = $scope.$root.steps;
        
              $scope.$watch(setOrdinal, function(value) {
                if (value)
                {
                  // steps code here
                }
              });
            }
          };
        });
        
        app.controller('stepController', ['$scope', '$rootScope', 'GetSteps', function ($scope, $rootScope, GetSteps) {
          var s = $scope;
          var r = $rootScope;
        
          s.initialize = function(id)
          {
            GetSteps.get({id: id}, function(resp){
              r.steps = resp.steps;
            });
          };
        }]);
        

        【讨论】:

        • 节省了我很多时间
        猜你喜欢
        • 1970-01-01
        • 2020-03-26
        • 2014-07-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-09
        相关资源
        最近更新 更多