【问题标题】:Angular - changes to directive controller's scope aren't reflected in viewAngular - 对指令控制器范围的更改不会反映在视图中
【发布时间】:2016-10-06 14:58:05
【问题描述】:

对我的作用域变量foo 的更改将在 html 中更新。当该值在指令的控制器范围内发生变化时,它不会在 html 中更新。

我需要做什么才能更新?

我有一个简单的example

app.js

var app = angular.module('app', []);

app.controller('ctrl', function($scope) {
  $scope.foo = 99;

  $scope.changeValue = function() {
    $scope.foo = $scope.foo + 1;
  }
});

app.directive('d1', function(){
  return {
    restrict: 'E',
    scope: {
      theFoo: '='
    },
    templateUrl: 'd1.html',
    controller: 'd1Ctrl',
  }
});

app.controller('d1Ctrl', function($scope) {
  $scope.test = $scope.theFoo;
});

d1.html

<div>
  <p>The value of foo is '{{theFoo}}'.</p>
  <p>The value of test is '{{test}}'.</p>
</div>

在 index.html 中

<d1 the-foo='foo'>
</d1>

<button ng-click='changeValue()'>change value</button>

总而言之,{{theFoo}} 正在更新,但 {{test}} 没有。为什么?

【问题讨论】:

    标签: angularjs angularjs-directive angularjs-scope angular-controller


    【解决方案1】:

    原因是$scope.foo 的值是一个原语。

    在指令控制器中,您只在控制器初始化时分配一次$scope.test。基元不像对象那样继承,所以在初始分配之后$scope.test 没有任何改变

    如果您使用对象而不是传入...继承将生效并且您会看到更改...否则您需要观看$scope.theFoo并自己更新$scope.test

    【讨论】:

    • 这是我在使用 Angular 时遇到的问题之一。尽管使用 controller-as 似乎避免了大多数这些令人头疼的问题,因为它被视为非原始的,但我仍然不喜欢我们必须重新考虑原始值更新的方式
    • @jusopi 如果您遵循最佳实践并使用对象而不是原语,整个问题就会消失。我很少在我的代码中使用 $watch 并确保我在视图中使用对象属性而不是原语
    • 很抱歉,说整个问题消失了是不正确的。除非他更改指令的内部工作以从非原始绑定值中提取测试值,否则test 仍然没有更新。 plnkr.co/edit/bRrQ9z4oBYrdBCLwbOjP?p=preview
    • @jusopi 但它仍然传递一个原语而不是一个对象
    • 那么他的指令必须对传入的非原始数据有所了解。我认为这是糟糕的设计。我宁愿阻止 $watch 语句的性能损失,也不愿让指令“知道”对象的属性。
    【解决方案2】:

    只有在链接控制器时确实设置了该值时,控制器中的代码才会初始化为该值。任何后续更改都不起作用。

    如果要绑定任何后续更改,则需要在控制器或链接函数中设置 $watch 语句。

    $scope.$watch( 'theFoo', function(val){ $scope.test = val; })
    

    更新的 plunker - http://plnkr.co/edit/eWoPutIJrwxZj9XJu6QG?p=preview

    【讨论】:

      【解决方案3】:

      这里你已经隔离了指令的范围,所以testd1.html不可见,如果你需要更改testtheFoo,你必须首先使它对指令可见

      app.directive('d1', function(){
        return {
          restrict: 'E',
          scope: {
            theFoo: '=',
            test : '=' //getting test as well
          },
          templateUrl: 'd1.html',
          controller: 'd1Ctrl',
        }
      });
      

      并且在 index.html 中,您应该将值传递给测试 &lt;d1 the-foo='foo' test='foo'&gt;&lt;/d1&gt;

      在上面的代码中你的控制器没有多大用处,即使没有这部分controller: 'd1Ctrl',代码也能正常工作。 在这个例子中你不必使用$watch

      【讨论】:

      • 这是一个简单的例子来演示我的问题 - test 是在指令控制器的范围内定义的 - 所以它必须是可见的。另外,它最初会获得价值,但它不会更新。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-23
      • 2016-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多