$ scope是全球性的

时间:2016-10-04 18:55:28

标签: javascript angularjs angularjs-directive angularjs-scope

我试图学习指令,我有一堆看起来像我的代码的指令。但由于某种原因,如果我定义的每个指令都有一个" $ scope.data"或者" $ scope.takeInClick",它似乎从最后一个加载的指令中得到了定义......

例如,如果" $ scope.data ='你好'"在一个指令中," $ scope.data =' hi'" ...如果后一个指令最后加载,但是如果我在console.log($ scope.data)中以前的指令,它会显示' hi'代替。

这很麻烦,我不确定为什么会这样?或者它是否有意?我认为这是$ rootScope的用途,不是 $ scope。我尝试将$ scope注入指令定义,但Angular似乎并不喜欢这样。

有人可以帮助或解释,谢谢你

app.directive('someDirective', function (SomeFactory1, SomeFactory2) {

var controller = function ($scope) {

    $scope.data;  //Defined in all of my directives

    function Initialize() {
        $scope.data = {
            stuff: ''
        }
    }

    Initialize();

    $scope.takeInClick = function () {  //Defined in all of my directives too
        //Do Something
    }

};

return {
    templateUrl: 'App_Data/Directives/Something/Something.html',
    controller: controller
}
});

3 个答案:

答案 0 :(得分:1)

它有点违反直觉,但angularJS中的$ scope不一定是孤立的。您可以在一个控制器中定义一个范围变量,并从同一级别的另一个控制器访问它,就像它是该控制器范围的一部分一样,这既强大又危险。最简单的解决方案是尽可能在$ scope范围内使用控制器变量和controllerAs语法,但在很多情况下,$ scope是正确的选择,并且通过练习,您将学会识别哪个是合适的。

如果您正在使用$ scope,请记住一些做法。第一个,也可能是最重要的是,在语义上和具体地命名您的变量。如果具有相似功能或元素的相邻范围,则使用通用名称可能会导致问题。我遇到了我的一个指令中出现错误的情况,因为同一页面上的另一个指令意外地覆盖了一个具有相同名称的函数,因此它使用了错误的数据。通过更具体地说,你也更安全,每次使用该变量时写一些额外的字符是为了安心和可读代码而付出的代价。

另一种解决方案是使用isolated scopes(搜索:隔离指令的范围)。隔离范围的工作方式与您期望的更为接近,您在该范围级别定义的任何内容都无法在当前范围及其子项之外访问。但是,您必须注意您隔离的范围,因为任何元素只能访问单个隔离范围。如果您有要一起工作的属性指令,给它们隔离的范围将导致编译错误。

要在代码中添加隔离范围,只需将其定义为对象的一部分,如下所示:

app.directive('someDirective', function (SomeFactory1, SomeFactory2) {

var controller = function ($scope) {

    $scope.data;  //Defined in all of my directives

    function Initialize() {
        $scope.data = {
            stuff: ''
        }
    }

    Initialize();

    $scope.takeInClick = function () {  //Defined in all of my directives too
        //Do Something
    }

};

return {
    templateUrl: 'App_Data/Directives/Something/Something.html',
    scope: {}, //Scope is now isolated!
    controller: controller
}
});

您还可以通过指令中的属性添加要注入范围的变量。

<强> HTML

<my-directive lines="parentScopeVariable.lineCount"></my-directive>

<强> JS

'use strict';

angular
  .module('myModule')
  .directive('myDirective',
    ['$rootScope', function ($rootScope) {

    return {
      restrict: 'E',
      scope:
      {
        lines: '=lines'
      },
      templateUrl: 'views/templates/my-directive.html',
      link: function ($scope, element, attributes, controller) {},
      controller: function ($scope)
      {
        //Lines is equal to whatever value the variable outside
        //the scope had, and uses two-way binding like you
        //would expect
        console.log ($scope.lines);
      }
    }]);

补充阅读:Understanding ScopeMastering the Scope of the Directives in AngularJS,其他任何博客文章或相关文章。

这方面有大量资源。不要害怕继续寻找,直到找到一个真正与你的学习风格产生共鸣的东西。在我的案例中,阅读文档就像把头撞在墙上一样,但在阅读我发现的随机博客文章时,指令开始有意义,同时寻找不同问题的答案。

答案 1 :(得分:1)

在您的指令中使用controllerAs语法,以避免像上面那样的范围问题:

      angular.module('your_module').directive('someDirective', someDirective);

      function someDirective(){
                   var directive = {
                   templateUrl: 'App_Data/Directives/Something/Something.html',
                  controller: ExampleController,
                  controllerAs: 'vm',
                  bindToController: true};

                  return directive;
                  }


      function ExampleController() {
            var vm = this;
            vm.data = '';
       }

这将有助于将外部范围更容易绑定到指令的控制器范围

通过将bindToController设置为true,它将帮助您将外部范围绑定到指令的控制器范围

答案 2 :(得分:-2)

尝试手动将范围注入控制器:

controller.$inject = ['$scope'];