【问题标题】:Accessing component $scope inside directive in 1.5在 1.5 中访问组件 $scope inside 指令
【发布时间】:2017-05-31 04:45:24
【问题描述】:

我正在使用 Angularjs 组件和 ES6 来构建一个也使用 d3js 的应用程序。我正在使用属性指令进行 DOM 操作。由于组件具有范围,我试图在链接函数中访问它并在内部使用 $watch。我的怀疑来自我试图观察和访问的变量在 $scope.$ctrl 内。在这种情况下访问它们的正确方法是什么?

模板

<div class="card">
    <svg network-svg>
    </svg>
</div>

组件

export const NetworkComponent = {

    template,
    controller: class NetworkComponent {

        constructor(CommService) {
            'ngInject'
            this.comm = CommService;
            this.physicalTree = new NodeTree('physical');
            this.virtualTree = new NodeTree('virtual');
            this.pVisible = true;
        }
    }
}

指令 当前指令的代码,但返回未定义。

export const NetworkSvg = () => {

    return {
        restrict: 'A',
        link($scope, $element, $attrs) {
            $scope.$watch('virtualTree', function() {

            });

            $scope.$watch('physicalTree', function() {

            });
     }
}

【问题讨论】:

    标签: javascript angularjs ecmascript-6


    【解决方案1】:

    我发现一个语法错误: 你能用这个替换指令代码吗……然后试试

    export const NetworkSvg = () => {
    
        return {
            restrict: 'A',
            link: ($scope, $element, $attrs) => {
                $scope.$watch('virtualTree', () => {
    
                });
    
                $scope.$watch('physicalTree', () => {
    
                });
         }
    }
    

    【讨论】:

      【解决方案2】:

      在我看来,如果你将属性传递到你的指令中,当它显然依赖于它们时,它会更清楚。例如

      <svg network-svg virtual-tree="virtualTree" physical-tree="physicalTree">
      

      然后您就可以在链接函数的$attrs 属性以及控制器的范围内访问这些值。

      【讨论】:

      • 可能是一个愚蠢的问题,但这是否与用作属性的指令兼容?
      • 在学习时没有愚蠢的问题! ;) 是的,它完全兼容。无论指令是使用元素名、属性还是类名定义的,都可以通过这种方式传递属性。
      【解决方案3】:

      $ctrl 对象是范围的属性。只需在手表中使用它:

      export const NetworkSvg = () => {
      
          return {
              restrict: 'A',
              link: ($scope, $element, $attrs) => {
                  //$scope.$watch('virtualTree', function() {
                  $scope.$watch('$ctrl.virtualTree', function(newValue) {
                       console.log(newValue);    
                  });
      
                  //$scope.$watch('physicalTree', function() {
                  $scope.$watch('$ctrl.physicalTree', function(newValue) {
                       console.log(newValue);    
                  });
               }
           }
      }
      

      在底层,AngularJS 框架在为组件实例化控制器时使用controller as $ctrl。控制器的this 上下文设置为组件作用域的$ctrl 属性。


      所以在这种情况下,使用$scope.$ctrl.physicalTree 访问它没有害处?

      作为稳健设计,最好避免将模型变量名称硬连线到自定义指令中。而是使用属性来定义名称:

      export const NetworkSvg = () => {
      
          return {
              restrict: 'A',
              link: (scope, element, attrs) => {
                  //scope.$watch('virtualTree', function() {
                  //scope.$watch('$ctrl.virtualTree', function() {
                  scope.$watch(attrs.virtualTree, function(newValue) {
                      console.log(newValue);    
                  });
      
                  //scope.$watch('physicalTree', function() {
                  //scope.$watch('$ctrl.physicalTree', function() {
                  scope.$watch(attrs.physicalTree, function(newValue) {
                      console.log(newValue);
                  });
              }
          }
      }
      

      然后使用属性定义接线:

       <my-component virtual-tree="$ctrl.virtualTree"
                     physical-tree="$ctrl.physicalTree" ></my-component>
      

      这也使得接线清晰的指令更加通用。


      我很难使用此解决方案,因为据我尝试和阅读,通过属性执行此操作,传递的值只是字符串文字。我将如何传递对象?

      在后台,$watch 使用 scope.$eval 来评估 Angular 表达式。其他代码也可以使用:

      例如:

      <div my-event="$ctrl.handle($event)"></div>
      

      JS:

      link: (scope,elem,attrs) => {
          elem.on("someEvent", function(e) {
              scope.$eval(attrs.myEvent({$event: e});
              scope.$apply();
          });
      }
      

      有关详细信息,请参阅

      【讨论】:

      • 所以在这种情况下使用 $scope.$ctrl.physicalTree 访问它并没有什么坏处?
      • 非常感谢,这正是我对它的怀疑,似乎有点做作。但我认为属性是要走的路。
      • 对不起,有点急于接受,因为它非常有意义。我很难使用这个解决方案,因为据我尝试和阅读,通过属性执行此操作,传递的值只是字符串文字。我将如何传递对象?
      • 好吧,我的错误,到目前为止,您的所有解释都是正确的。我的错误是我在侦听器函数中调用 attrs.physical 很明显它只是一个字符串文字。添加了 value 参数,它工作得很好。非常感谢您的宝贵时间。
      猜你喜欢
      • 2017-07-23
      • 1970-01-01
      • 2017-08-15
      • 1970-01-01
      • 1970-01-01
      • 2016-05-16
      • 1970-01-01
      • 1970-01-01
      • 2016-12-15
      相关资源
      最近更新 更多