在Angular指令中继承父级的新作用域

15

假设我这样做:

sAngular.app.directive('dostuff', ['$compile', function($compile){
  return   {
    restrict : 'C',
    scope: {
      someVar : '='
    },
    link : function(scope, element, attrs){  
      element.click(function(){
           //do stuff
        scope.someVar = 'somethingelse';
        var dropdownOutput = template();
        var compiledOutput = $compile(dropdownOutput)(scope);
        scope.$apply();
     });
    }    
  }
}]);

如何让这个指令的作用域继承父级作用域的变量,同时仍然拥有一个“隔离”的作用域?

例如来自Angular文档中的:

=或=attr-在本地作用域属性和通过值定义的名称的父级作用域属性之间设置双向绑定。如果未指定attr名称,则假定属性名称与本地名称相同。给定scope: {localModel:'= myAttr'},那么widget作用域属性localModel将反映父级作用域中parentModel的值。对parentModel进行的任何更改都将反映在localModel中,对localModel进行的任何更改都将反映在parentModel中。

但是,在这种情况下,由于“对localModel进行的任何更改都将反映在parentModel中”,如果我在该指令的作用域中修改一个变量,然后执行scope.apply(),那么它将相应地反映在父级作用域中,并且父模板将更新其更改。

我也尝试了将"scope:true"作为参数,但在该作用域中所做的更改以及scope.$apply()也会传播到原始作用域...

是否有一种方法可以使我复制父作用域的作用域,同时仍然不让该作用域中的变量更改传播到父作用域?


不是很清楚你想要什么,有提供概述情况的演示吗?compiledOutput在做什么还不是很清楚。 - charlietfl
如果您不想将隔离作用域属性更改传播到父作用域,则请使用@而不是=。抱歉,我做出了更正。 - Rajkamal Subramanian
1
@rajkamal,使用&符号会将作用域变量转换为函数,而不是让作用域变量从父作用域变量继承。 - pillarOfLight
@rajkamal,使用@也不起作用……这应该引用dom属性元素,值将始终是字符串,而不是作用域变量(请参阅http://docs.angularjs.org/guide/directive scope部分) - pillarOfLight
你尝试过在指令中使用scope.$parent.variableName吗? - Ketan
这是一个重复的问题,链接为https://dev59.com/cG_Xa4cB1Zd3GeqP6u0z,那里有一个非常好的答案。 - Roy Truelove
1个回答

12
使用“继承”这个词有点令人困惑。隔离作用域(isolate scope)不会从其父作用域(parent scope)中继承。Angular确实在隔离作用域上放置了一个$parent属性,因此您可以通过这种方式访问父作用域属性,但最佳实践是不要使用$parent。如果要使用隔离作用域,将父作用域属性值传递到该隔离作用域的唯一方法是使用=,@或&。所有三个都可以使用(甚至'&'也可以通过表达式传递属性值 - 好奇的人)。
在您的隔离作用域上(或者如果您使用scope:true),您可以创建新属性。这些新属性不会传播回父级。因此,如果要更改传递到指令的属性值,则可以将其复制到指令范围的某个新属性中。
这里是一个使用@的示例,它是"单向字符串"语法。要在HTML中获取父级作用域属性的(插值)值(以字符串形式),请使用{{}}:
<div class="dostuff" some-var="{{interpolateThisParentScopePropertyPlease}}">

sAngular.app.directive('dostuff', ['$compile', function($compile){
  return   {
    restrict : 'C',
    scope: { someVar : '@' },
    link : function(scope, element, attrs){  
      element.click(function(){
        scope.myLocalDirectiveProperty = scope.someVar;
        scope.someOtherDirectiveProperty = 'somethingelse';
        var dropdownOutput = template();
        var compiledOutput = $compile(dropdownOutput)(scope);
        scope.$apply();
     });
    }

如果你想将一个对象传递给指令,使用“=”语法,然后在指令内部使用angular.copy()复制该对象。
根据评论请求:
<div class="dostuff" some-obj="parentScopeObj">

sAngular.app.directive('dostuff', ['$compile', function($compile){
  return   {
    restrict : 'C',
    scope: { someObj : '=' },
    link : function(scope, element, attrs){  
      element.click(function(){
        scope.myLocalDirectiveObjProperty = angular.copy(scope.someObj);
        ...
        scope.$apply();
     });
    }

谢谢您的回复,您能给我一个'='语法传递对象的例子吗?因为这正是我感兴趣的。 - kamikaze_pilot
如果您想使用与父作用域相同的变量名称,该怎么办?有什么方法吗?如果我将some-obj设置为parent-scope-obj,并在指令中修改scope.parentScopeObj,那么它会影响父作用域的parentScopeObj吗? - kamikaze_pilot
请看这个回答是否解决了你的问题:在HTML中使用的属性名称(例如parent-scope-obj)与父作用域属性名称无关。例如,假设父作用域属性是prop1,并且您将其传递给指令作为<div class="dostuff" parent-scope-obj="prop1"...>。在指令中,您可以使用以下语法将传递的属性命名为任何您想要的名称,比如dirProp1scope: { dirProp1: '=parentScopeObj' }。现在,指令作用域属性dirProp1和父作用域属性prop1是“链接”的——更改其中任何一个都会始终更改另一个。 - Mark Rajcok

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接