如何将模型或字符串传递给 angularjs 中的指令?

how to pass either a model or a string to a directive in angularjs?

我正在处理一个指令,其中一个参数可以是模型(动态值),有时也可以是字符串。

我能做到这一点的唯一方法是使用 @。有更好的方法吗?

<my-directive foo="{{foomodel}}">
<my-directive foo="foostring">

在我的指令中,我使用了隔离范围:

scope: {
    foo: '@'
}

我试过只用字符串来做,但没用。

只要你有字符串值,你就应该把它包在 ' 单引号里, 因为 @ 表示使用 $parse API of angular

的表达式求值

HTML

<my-directive foo="'foostring'">

希望对您有所帮助,谢谢。

如果您使用隔离范围,则可以使用双向绑定:"="。这将采用以下方式采用模型或文字(假设 $scope.model = "test":

<div foo="model"></div>       <!-- test | string -->
<div foo="'text'"></div>      <!-- text | string -->
<div foo="5"></div>           <!-- 5 | number -->
<div foo="{a: 5}"></div>      <!-- {"a":4} | object -->

这是指令定义:

app.directive("foo", function(){
  return {
    scope: {
      foo: "="
    },
    template: "<span>{{foo}}</span> | <span>{{type}}</span>",
    link: function(scope){
      scope.type = typeof scope.foo;
    }
  }
})

plunker

编辑:

根据@JoeEnzminger 的反馈,"=" 是获取实际对象的一种昂贵方式,因为它设置了 2 个观察者(用于双向绑定)。

对于单向绑定(只有一个观察者)

您可以 foo: "@" 绑定。这将导致所有值都被解释为 string。具体来说,要传递 $scope.model 的值,您需要使用表达式:{{model}}.

或者,如 所建议,您可以使用 foo: "&" 绑定。这将允许返回实际的 model/object 。缺点是表达式的函数语法更笨拙 {{foo()}}

一次性绑定:

如果可以取消一次性绑定,则可以使用 $parse 服务来获取实际对象。

对于隔离范围:

scope: {}, 
link: function(scope, element, attrs){
  scope.foo = $parse(attrs.foo)(scope.$parent);
}

对于继承范围:

scope: true,
link: function(scope, element, attrs){
  scope.foo = $parse(attrs.foo)(scope);
}

阅读这些答案,似乎在使用独立作用域时对“=”、“&”和“@”之间的区别存在很多混淆。出于您的目的,我会使用 & 并且如果您希望该值是一个字符串或一个对象,请按照@pankajparkar 的做法并将字符串括在单引号中。

除非您需要将指令中的更改反映在父作用域中,否则不要使用“=”。 '=' 隐式设置对隔离作用域 属性 的监视,并在发现更改时修改父作用域 属性。监视在 Angular 中是一项相对昂贵的操作,您希望将它们最小化。

& 不会隐式创建一个监视,它会在您调用创建的作用域函数时推迟对表达式的求值。它非常适合您的情况,因为您不需要双向绑定。将 & 视为创建一个函数,该函数 returns 由分配给属性的表达式生成的值。

app.directive("foo", function(){
  return {
    scope: {
      foo: "&"
    },
    template: "<span>{{foo()}}</span> | <span>{{typeof foo()}}</span>",
    link: function(scope){
        //so we don't have to set up a watch, I've just inlined the evaluation of the type
    }
  }
})

<div foo="model"></div>       <!-- test | string -->
<div foo="'text'"></div>      <!-- text | string -->
<div foo="5"></div>           <!-- 5 | number -->
<div foo="{a: 5}"></div>

@ 保留用于您希望将表达式的计算限制为插值的情况。 angular 中的插值总是会产生一个字符串。如果您使用“@”并且您的属性不是插值表达式 ({{}}),则范围 属性 的值将是属性的字面值。如果您的属性值是插值表达式,则 属性 的值将是表达式的插值(始终是字符串)。

一尘不染吧?