在指令中从 attr 的角度保存手表表达式

Angular save watch expression from attr in directive

本文关键字:保存 手表 表达式 指令 attr      更新时间:2023-09-26

我想在指令中将一些html传递给attr,我遇到的问题是我所做的不保存绑定它只是显示初始值,我如何在这里完成数据绑定?

function link( $scope, elem, attrs, ctrl, transclude ) {
    $scope.dropDownClass = attrs.ddClass || 'default';
    var main = $compile(attrs.main)($scope);
    elem.find('button').first().append(main);
  }
<my-drop-down main='<a><img src="images/flags/en.png" alt="en"/>{{name}}</a>'>
 <li><a><img src="images/flags/en.png" alt="en"/>En</a></li>
</my-drop-down>

我希望 {{name}} 仍然绑定到我的控制器。

http://plnkr.co/edit/IrF1dIZslCEQf0FOfNJi?p=preview

好的,我快速浏览了一下。据我所知,在attr查找之前正在评估主要属性。所以,你实际编译<a>World</a>不是<a>{{name}}</a>

我认为没有办法告诉 angular 不评估属性(标记有 ngNonBindable,但这对我们没有帮助)。我看到您的问题的两种解决方案。

选项 #1:您可以从属性中提取所需的模板字符串,而是将其附加到 MainCtrl 中的范围。看起来像这样:http://plnkr.co/edit/M6GZJDVHuW8op2Zo11mJ?p=preview

// Markup:
<my-drop-down> ...
// MainCtrl:
app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';
  $scope.main = '<a>{{name}}</a>';
});
// Then, in your directive link:
function link($scope, elem, attrs, ctrl, transclude ) {
  $scope.dropDownClass = attrs.ddClass || 'default';
  // Use scope.main, instead of attrs.main:
  var main = $compile($scope.main)($scope);
  elem.find('button').first().append(main);
}

选项#2:如果您想将模板字符串的传递保留在属性中,据我所知,我们不能使用大括号并期望它们作为大括号传递。因此,我们可以尝试使用其他对我们的代码足够独特的东西。我选择了%%,但它可以是你想要的任何东西,真的。这看起来像这样:http://plnkr.co/edit/760CFsq9sF9lIBHgO2Ic?p=preview

// Markup:
<my-drop-down main="<a>%%name%%</a>">
// Then, in your directive link:
function link($scope, elem, attrs, ctrl, transclude ) {
  $scope.dropDownClass = attrs.ddClass || 'default';
  // Replace our template string and compile that w/ braces:
  var tpl = attrs.main.replace(/%%([a-z]+)%%/g, '{{$1}}');
  var main = $compile(tpl)($scope);
  elem.find('button').first().append(main);
}

您还可以采用其他选项,例如创建隔离范围等,但它们需要对代码进行更多重构。以上两个似乎是最容易插入的。

问题是当你执行链接函数时,name已经值了。

除了@rgthree所说的之外,您还可以在指令上使用 compile 函数来仅调用 var compiled = $compile(tAttrs.main),然后在链接函数中调用范围为 var main = compiled($scope) 的返回值:

compile: function compile(tElement, tAttrs, transclude) {
      var compiled = $compile(tAttrs.main);
      return function( $scope, elem, attrs, ctrl, transclude ) {
          $scope.dropDownClass = attrs.ddClass || 'default';
          console.log(3);
          var main = compiled($scope);
          elem.find('button').first().append(main);
      }
    },

检查这个弹道