将params传递给具有隔离范围的嵌套指令

ces*_*pon 9 data-binding scope directive angularjs

我有一个对象data中MainCtrl.该对象用于将数据传递给指令first-directive和second-directive.在两种情况下都需要双数据绑定.

因为first-directive,我传递完整的对象,data但second-directive我想传递numbersobject(scope.numbers = scope.dataFirst.numbers).

问题:

当我这样做<div second-directive="dataFirst.numbers"></div>,并检查是否dataSecond是一个对象时,它返回true.

但当我这样做<div second-directive="numbers"></div>,我检查是否dataSecond是一个对象,它返回false.

在这两种情况下,如果我这样做console.log(scope),显示scope.dataSecond属性.

问题:

为什么会发生这种情况以及将params传递给指令的正确方法是什么?

编辑: 这个想法是制定可重复使用的指令,这意味着他们不能依赖其他指令.

angular.module('app',[])

.controller('MainCtrl', function($scope) {
  $scope.data = {
    numbers: {
      n1: 'one',
      n2: 'two'
    },
    letters: {
      a: 'A',
      b: 'B'
    }
  }
})

.directive('firstDirective', function () {
  return {
    template: '<div class="first-directive">\
      <h2>First Directive</h2>\
      {{dataFirst}}\
      <div second-directive="dataFirst.numbers"></div>\
      <div second-directive="numbers"></div>\
      </div>',
    replace: true,
    restrict: 'A',
    scope: {
      dataFirst: '=firstDirective'
    },
    link: function postLink(scope, element, attrs) {
      console.log('first directive')
      console.log(scope)
      scope.numbers = scope.dataFirst.numbers;
    }
  };
})

.directive('secondDirective', function () {
  return {
    template: '<div class="second-directive">\
      <h2>Second Directive</h2>\
      {{dataSecond}}\
      <div class="is-obj">is an object: {{isObj}}</div>\
      </div>',
    replace: true,
    restrict: 'A',
    scope: {
      dataSecond: '=secondDirective'
    },
    link: function postLink(scope, element, attrs) {
      console.log('second directive');
      console.log(scope)
      
      // <div second-directive="XXXX"></div>
      // if 'numbers' returns undefined
      // if 'dataFirst.numbers' returns the object
      console.log(scope.dataSecond); 
      
      scope.isObj = false;
      
      if(angular.isObject(scope.dataSecond)){
        scope.isObj = true;
      }
    }
  };
});
Run Code Online (Sandbox Code Playgroud)
h2 {
  padding: 0;
  margin: 0;
}

.first-directive {
  background: #98FFDA;
  color: black;
  padding: 10px;
}

.second-directive {
  background: #FFA763;
  color: white;
  padding: 10px;
}

.is-obj {
  background: blue;
}
Run Code Online (Sandbox Code Playgroud)
<!DOCTYPE html>
<html ng-app="app">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
  </head>

  <body ng-controller="MainCtrl">
    <h2>MainCtrl</h2>
    {{data}}

    <div first-directive="data">
    </div>

    <div second-directive="data">
    </div>
  </body>

</html>
Run Code Online (Sandbox Code Playgroud)

New*_*Dev 11

我重复我以前别人怎么说-该link功能firstDirective是后期运行连杆式功能后,该link功能secondDirective,所以scope.numbers还没有分配的对象scope.dataFirst.numbers.

然而,通过紧密耦合两个指令的解决方案require对我来说似乎不是最优的.

相反,为了确保在内部/子指令运行之前在父级中正确分配了一个scope属性(比如secondDirective在这种情况下)是在(而不是post -link)中使用预链接函数firstDirective

link: {
  pre: function prelink(scope){
      console.log('first directive')
      console.log(scope)
      scope.numbers = scope.dataFirst.numbers;
    }
}
Run Code Online (Sandbox Code Playgroud)

演示


Jul*_*obs 8

我的解决方案是让第二个指令从第一个指令继承数据对象属性.

angular.module('app', [])

.controller('MainCtrl', function($scope) {
  $scope.data = {
    numbers: {
      n1: 'one',
      n2: 'two'
    },
    letters: {
      a: 'A',
      b: 'B'
    }
  }
})

.directive('firstDirective', function() {
  return {
    template: '<div class="first-directive">\
      <h2>First Directive</h2>\
      {{dataFirst}}\
      <div second-directive></div>\
      <div second-directive></div>\
      </div>',
    replace: true,
    restrict: 'A',
    scope: {
      dataFirst: '=firstDirective'
    },
    controller: function firstDirectiveController($scope) {
      return $scope;
    },
    link: function postLink(scope, element, attrs) {
      console.log('first directive')
      console.log(scope)
      scope.numbers = scope.dataFirst.numbers;
    }
  };
})

.directive('secondDirective', function() {
  return {
    template: '<div class="second-directive">\
      <h2>Second Directive</h2>\
      {{dataSecond}}\
      <div class="is-obj">is an object: {{isObj}}</div>\
      </div>',
    replace: true,
    require: '^firstDirective',
    link: function postLink(scope, iElement, iAttrs, firstDirectiveController) {
      console.log('second directive');
      console.log(firstDirectiveController.dataFirst.numbers);
      
      scope.dataSecond = firstDirectiveController.dataFirst.numbers;

      scope.isObj = false;

      if (angular.isObject(scope.dataSecond)) {
        scope.isObj = true;
      }
    }
  };
});
  
Run Code Online (Sandbox Code Playgroud)
h2 {
  padding: 0;
  margin: 0;
}

.first-directive {
  background: #98FFDA;
  color: black;
  padding: 10px;
}

.second-directive {
  background: #FFA763;
  color: white;
  padding: 10px;
}

.is-obj {
  background: blue;
}
Run Code Online (Sandbox Code Playgroud)
  
<!DOCTYPE html>
<html ng-app="app">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
      <link rel="stylesheet" href="style.css">
    <script src="script.js"></script>
  </head>

  <body ng-controller="MainCtrl">
    <h2>MainCtrl</h2>
    {{data}}

    <div first-directive="data">
    </div>
  </body>

</html>
Run Code Online (Sandbox Code Playgroud)

  • 如果你知道html中指令的嵌套顺序,这是一个很好的答案.我的想法是制作可重复使用的组件(如下拉列表),这意味着您不知道订单.例如,如果你试图将`second-directive`放在`<body>`中,它就不起作用,因为它需要`first-directive`.谢谢 :) (2认同)
  • 这个解决方案肯定有效(尽管它不必要地将两个指令紧密地结合在一起),但一个好的答案应该不仅仅是代码. (2认同)