为什么我们不能使用“ng-model”插值表达式,但可以使用“ng-src”?

时间:2015-05-16 08:08:43

标签: angularjs angularjs-directive

我试图将插值表达式与ng-model指令一起使用,但它不起作用。相反,当我使用ng-src插值时,它的工作完全正常。这有什么不同?

3 个答案:

答案 0 :(得分:3)

这一切都取决于指令的设置方式。

某些指令(如ng-modelng-showng-click不使用插值符号,而指令ng-src采用插值。

仅对字符串起作用的指令支持插值。如果我们看一下ng-src实现,你会发现

 attr.$observe(normalized, function(value) {
          if (!value)
             return;

          attr.$set(attrName, value);

          if (msie) element.prop(attrName, attr[attrName]);
        });

attr.$observe监视属性而非模型的变化。模型更改会导致属性更改(由于插值),从而导致触发器触发。

对于像ng-model这样的所有其他指令,属性值是一个在当前范围内计算的表达式,并不限于字符串值。

如果您正在开发自己的指令,隔离的范围属性=@可帮助您实现类似的功能。

答案 1 :(得分:0)

当指令中的代码查看属性时:插值之前或之后。

我怀疑ngModel使用了该属性,我的意思是将其传递给$parse$eval,因为它是之前插值。

但是,指令ngSrc使用该属性,我的意思是将src属性设置为属性值,插入之后

为什么ngModel在插值之前使用该值的原因,但是ngSrc之后使用它,我怀疑它是如何编码的。考虑指令

<my-directive my-attr="{{ 'name' }}"></my-directive>

编码为:

app.directive('myDirective', function() {
  return {
    restrict: 'E',
    link: function($scope, $element, $attrs) {
      console.log('Link:', $attrs.myAttr);       // Outputs "name"
    },
    controller: function($scope, $element, $attrs) {
      console.log('Controller:', $attrs.myAttr); // Outputs "{{ 'name' }}"
    }
  };
});

在控制器中可以看到未插值的值,但在链接功能中可以看到后插值。所以(相关)事件的顺序是

  • 控制器,
  • 然后插值,
  • 然后链接功能。

你可以see this example in a Plunker。我怀疑ngModel使用控制器中的值,因此看到预插值,但ngSrc使用链接函数,因此看到后插值。

为什么ngModel使用控制器而不是链接函数的一个原因,我怀疑它是否可以将控制器暴露给其他指令,这些指令可以通过require选项使用它。 / p>

一个稍微有点混淆的并发症是ngSrc不希望该属性是有效的Angular表达式。它不是通过$parse$eval传递,而是直接使用属性的后插值。 (即它不需要将URL包装在引号中)。

如果您愿意,可以编写一个将插值与Angular表达式结合起来的指令。在链接功能中,您可以将属性传递给$parse$eval。如果后插值的值是有效的Angular表达式,这将起作用。您可以从控制器执行相同的操作,但您必须先通过$interpolate传递值。

正如您所发现的,ngModel不支持此功能。但是,我不明白为什么你不能写一些支持这两者的基本版ngModel,因此可以用作

my-model="myScope{{ 'VariableName' }}"

访问范围变量myScopeVariableName

为了再次回到问题,为什么ngModel本身不支持这一点,我怀疑是因为用例有限(OP在问题中没有提到一个),所以会添加指令的复杂性没有充分的理由。

答案 2 :(得分:-1)

它与指令隔离范围提供的单向与双向数据绑定有关。查看&#34;隔离范围说明&#34;以下部分:

http://www.undefinednull.com/2014/02/11/mastering-the-scope-of-a-directive-in-angularjs/