angularjs 范围值更新时指令不更新

angularjs directive doesn't update when scope value update

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
    <script type="text/javascript">
      (function(){
        'use strict';
        angular.module('myApp',[])
        .controller('TestCtrl',TestCtrl)
        .directive('trxTablePersonTd',trxTablePersonTd);

        function TestCtrl($scope){
          var vm = $scope.vm = this;
          vm.trxs = [
            {id:"1",acctKey:"2",persons:[{name:'peter',age:20},{name:'hank',age:23}]},
            {id:"2",acctKey:"3",persons:[{name:'Joe'},{name:'Jason'}]}
          ];
          $scope.changePerson = function(){
            vm.trxs[1]['persons']['age'] = 33;
            vm.trxs[1]['acctKey'] = 123;

          }
        }
        function trxTablePersonTd($compile){
            return{
              scope:{persons:'=persons'},
              restrict:'A',

              link:link,

              replace:false,
              //compile:compile
            }
            function compile(elem,attrs){
              return function(scope){
                var html = [];
                scope.persons.map(function(person,index){

                  html.push('<td>'+person.name+'</td>');
                  html.push('<td>'+person.age+'</td>');
                });

              }
            }
            function link(scope, elem, attrs){
              var html = [];

              if(scope.persons){
                scope.persons.map(function(person,index){

                  html.push('<td>'+person.name+'</td>');
                  html.push('<td>'+person.age+'</td>');
                });
              }
              elem.replaceWith(html.join(''));
              $compile(elem.contents())(scope);
            }

        }
      }());
    </script>
  </head>
  <body ng-app="myApp"  ng-controller="TestCtrl">
    <button type="button" name="button" ng-click="changePerson()">change person</button>
    <table border="1">
      <tbody>
        <tr ng-repeat="trx in vm.trxs">

          <td>
            {{trx.id}}
          </td>
          <td>
            {{trx.acctKey}}
          </td>
          <td trx-table-person-td  persons="trx.persons">

          </td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

Blockquote

当我点击按钮时,未定义的年龄没有得到更新。谁能帮我看看这个问题

当我点击按钮时,未定义的年龄没有得到更新。谁能帮我看看这个问题

我一直在等着看是否有人会比我更好、更权威地回答这个问题。我认为问题是因为范围更新没有像您的更改那样深入到数据结构中。我认为您需要在 vm.trxs 上实施深度监视 ("watch by value")。请参阅 https://docs.angularjs.org/guide/scope,向下滚动到 "Controllers and Scopes" 部分。

您没有在 $scope.changePerson 方法中正确更新 collection。 persons也是一个数组,应该像

$scope.changePerson = function () {
    vm.trxs[0]['persons'][0]['age'] = 33; //look ['persons'][0] 
    vm.trxs[0]['acctKey'] = 123;
}

正如@Ed Staub 建议的那样,您需要 $watch 您的 collection 来传播进一步的模型更改,例如

app.directive('trxTablePersonTd', function ($compile) {

    return {
        scope: { persons: '=persons' },
        restrict: 'A',
        link: link,
        replace: false,
    }

    function link(scope, elem, attrs) {
        if (scope.persons) {
            scope.$watch('persons', function () {
                var html = scope.persons.map(function (person, index) {
                    return '<td>' + person.name + '</td>' + '<td>' + (person.age ? person.age : "") + '</td>';
                });

                elem.empty().append(html.join(''));
                $compile(elem.contents())(scope);

            }, true);
        }
    }
});

此外,如果您的指令中除了 td 之外没有其他 html,我认为您根本不需要指令,只需使用 ng-repeat 喜欢

<td ng-repeat="person in trx.persons">
    <span>{{person.name}}</span>
    <span>{{person.age}}</span>
</td>