Javascript AngularJs:使用角度指令跨多个隔离作用域传递函数参数

Javascript AngularJs:使用角度指令跨多个隔离作用域传递函数参数,javascript,angularjs,Javascript,Angularjs,我有3个嵌套的、隔离的作用域、指令(),我能够将函数(带参数)从最外层的指令传递到最内层的指令(将函数从外层指令传递到中间指令,再传递到内层指令) 我无法理解的是,需要做什么才能将参数从内部指令传递回中间指令,再传递回外部指令 再一次,看 注意:只要给出2条隔离作用域指令,我就可以让它与以下类似的东西一起工作 angular.module('myApp', []) .directive('myDir1', function() { return { template: '

我有3个嵌套的、隔离的作用域、指令(),我能够将函数(带参数)从最外层的指令传递到最内层的指令(将函数从外层指令传递到中间指令,再传递到内层指令)

我无法理解的是,需要做什么才能将参数从内部指令传递回中间指令,再传递回外部指令

再一次,看

注意:只要给出2条隔离作用域指令,我就可以让它与以下类似的东西一起工作

angular.module('myApp', [])
  .directive('myDir1', function() {
    return {
      template: '<div><my-dir-2 add-name="addName(name)"></my-dir-2></div>',
      controller: function($scope) {
        $scope.addName = function(name) {
          alert(name); // alerts 'Henry'
        };
      }
    }
  })
  .directive('myDir2', function() {
    return {
      scope: {
        addName: '&'
      },
      template: "<span ng-click='addName({name: testName})'>Click to Add {{testName}}!</span>",
      controller: function($scope) {
        $scope.testName = 'Henry';
      }
    }
  });
angular.module('myApp',[])
.directive('myDir1',function(){
返回{
模板:“”,
控制器:功能($scope){
$scope.addName=函数(名称){
警报(名称);//警报“Henry”
};
}
}
})
.directive('myDir2',function(){
返回{
范围:{
addName:“&”
},
模板:“单击以添加{{testName}}!”,
控制器:功能($scope){
$scope.testName='Henry';
}
}
});
上面的代码给了我一个带有“Henry”的警告框(就像我预期的那样)

当我添加第三个中间的隔离范围指令时,我遇到了问题

angular.module('myApp', [])
  .directive('myDir1', function() {
    return {
      template: '<div><my-dir-2 add-name="addName(name)"></my-dir-2></div>',
      controller: function($scope) {
        $scope.addName = function(name) {
          alert(name); // alerts 'Henry'
        };
      }
    }
  })
  .directive('myDir2', function() {
    return {
      scope: {
        addName: '&'
      },
      template: '<div><my-dir-3 add-name="addName({name: testName})"></my-dir-3></div>',
    }
  })
  .directive('myDir3', function() {
    return {
      scope: {
        addName: '&'
      },
      template: "<span ng-click='addName({name: testName})'>Click to Add {{testName}}!</span>",
      controller: function($scope) {
        $scope.testName = 'Henry';
      }
    }
  });
angular.module('myApp',[])
.directive('myDir1',function(){
返回{
模板:“”,
控制器:功能($scope){
$scope.addName=函数(名称){
警报(名称);//警报“Henry”
};
}
}
})
.directive('myDir2',function(){
返回{
范围:{
addName:“&”
},
模板:“”,
}
})
.directive('myDir3',function(){
返回{
范围:{
addName:“&”
},
模板:“单击以添加{{testName}}!”,
控制器:功能($scope){
$scope.testName='Henry';
}
}
});

此代码为我提供了一个带有
未定义
的警报框。

您可以使用
isolateScope()

myDir1
指令中,将
控制器替换为该控制器

  link: function($scope, elem) {
    $scope.addName = function(name) {
      var e = elem.find('my-dir-3');
      var s = e.isolateScope();
      alert(s.testName);
    };
另一种方法是潜在地使用
$$nextSibling
来获取当前父级之后的下一个作用域(尚未真正使用此作用域,因此可能需要了解它)


这可能不是做事情的“有棱角的方式”。我认为从子指令中删除隔离作用域并让它们引用父指令模型会更理想。

在隔离作用域中传递函数有两种方法。虽然“&”将确保您传递的实际上是一个函数,但您也可以使用“=”作为绑定变量传递函数,并仅在需要时调用它。这种方法有缺点,但它将把调用的控制权留给负责该调用的组件

angular.module('myApp',[])
.directive('myDir1',function(){
返回{
模板:“”,
控制器:功能($scope){
$scope.addName=函数(名称){
警报(名称);
};
}
}
})
.directive('myDir2',function(){
返回{
范围:{
地址名称:'='
},
模板:“”
}
})
.directive('myDir3',function(){
返回{
范围:{
地址名称:'='
},
模板:“单击以添加{{testName}}!”,
控制器:功能($scope){
$scope.testName=“Henry”
}
}
});

带有三个嵌套指令的代码的问题是
testName
不存在于
myDir2
的独立范围内。您可以从
myDir3
进行设置,但为此,您必须在
myDir2
范围内创建一个对象,并将其属性设置为testName,然后在
myDir2
中使用该属性

工作示例如下
一个常见的误解是“&用于传递函数”。这在技术上是不正确的

&
所做的是在指令作用域上创建一个函数,当调用该函数时,返回针对父作用域计算的表达式的结果

此函数将对象作为参数,在本例中,该参数将使用指令作用域(
{name:testName}
)对象中的局部变量重写表达式中的局部变量

如果要查看引擎盖下的内容,则
myDir2
中的
$scope.addName
方法将如下所示(简化):

您的第二个指令可以工作,因为它绑定到的表达式是

addName(name)
此表达式有一个局部变量
name
,当使用执行时,该变量将被指令中的testName值覆盖

addName({name: testName}) //in the directive. 
请记住,
myDir2
中的
addName
函数与
myDir1
中的
addName
函数不同。它是一个计算表达式的新函数

addName(name) 
并返回结果

将此逻辑应用于
myDir3
时,计算的表达式为:

addName({name: testName})
请注意,此表达式中唯一的局部变量是“testName”。因此,当您使用

addName({name: testName})
没有要重写的局部变量
name
,并且
testName
未定义

呸!难怪这让所有人都感到困惑

如何在您的示例中修复:

您希望表达式计算为
myDir1
中的实际函数

angular.module('myApp', [])
  .directive('myDir1', function() {
    return {
      template: '<div><my-dir-2 add-name="addName"></my-dir-2></div>',
      controller: function($scope) {
        $scope.addName = function(name) {
          alert(name); // alerts 'Henry'
        };
      }
    }
  })
  .directive('myDir2', function() {
    return {
      scope: {
        addName: '&'
      },
      // addName() returns the actual function addName from myDir1
      template: '<div><my-dir-3 add-name="addName()"></my-dir-3></div>',
    }
  })
  .directive('myDir3', function() {
    return {
      scope: {
        addName: '&'
      },
      //calls addName() on myDir2, which returns addName from myDir1, then invokes it passing testName as an argument
      template: "<span ng-click='addName()(testName)'>Click to Add {{testName}}!</span>",
      controller: function($scope) {
        $scope.testName = 'Henry';
      }
    }
  });
angular.module('myApp',[])
.directive('myDir1',function(){
返回{
模板:“”,
控制器:功能($scope){
$scope.addName=函数(名称){
警报(名称);//警报“Henry”
};
}
}
})
.directive('myDir2',function(){
返回{
范围:{
addName:“&”
},
//addName()从myDir1返回实际的函数addName
模板:“”,
}
})
.directive('myDir3',function(){
返回{
范围:{
addName({name: testName})
angular.module('myApp', [])
  .directive('myDir1', function() {
    return {
      template: '<div><my-dir-2 add-name="addName"></my-dir-2></div>',
      controller: function($scope) {
        $scope.addName = function(name) {
          alert(name); // alerts 'Henry'
        };
      }
    }
  })
  .directive('myDir2', function() {
    return {
      scope: {
        addName: '&'
      },
      // addName() returns the actual function addName from myDir1
      template: '<div><my-dir-3 add-name="addName()"></my-dir-3></div>',
    }
  })
  .directive('myDir3', function() {
    return {
      scope: {
        addName: '&'
      },
      //calls addName() on myDir2, which returns addName from myDir1, then invokes it passing testName as an argument
      template: "<span ng-click='addName()(testName)'>Click to Add {{testName}}!</span>",
      controller: function($scope) {
        $scope.testName = 'Henry';
      }
    }
  });