当元素顺序改变时,重复出现奇怪的行为

时间:2018-01-31 11:29:45

标签: angularjs angularjs-ng-repeat

我正在学习angularjs,我遇到了一些我无法理解的行为。我在ng-repeat中渲染一个项目列表,每个项目都有一个从$ scope的数组中删除自己的按钮 - 这可以按预期工作,但是一旦我在列表中添加了一个可排序的奇怪事情就开始发生了。

以下是显示问题的运行示例:

https://embed.plnkr.co/eQWcxZ7p8CcACfk6Z53X/

在示例中 - 如果我将[^]项目4(火箭启动器)移动到位置1并使用Rocket Launcher的删除[X]按钮,则列表会更新(即项目4 - 火箭启动器 - 位于第1位的已删除)但其他项删除按钮停止工作。基本上移动项目并删除它们会以某种方式破坏绑定(?)。

代码:

(function() {
  'use strict';
  var app = angular.module('myApp', []);

  app.controller('myAppController', function($scope) {

    $scope.boxes = [];

    $scope.removeBoxItem = function(box, item) {
      console.log('Removing "' + item.name + '" form box "' + box.name + '"...');
      var index = box.items.indexOf(item);
      box.items.splice(index, 1);
      console.log(box);
    };

    this.init = function() {
      var e;
      e = new Box({
        name: 'Red box'
      });

      $scope.boxes.push(e);

      e.items.push(new Item({
        index: 1,
        name: 'Rock'
      }));
      e.items.push(new Item({
        index: 2,
        name: 'Scissors'
      }));
      e.items.push(new Item({
        index: 3,
        name: 'Paper'
      }));
      e.items.push(new Item({
        index: 4,
        name: 'Rocket launcher'
      }));

      e = new Box({
        name: 'Green box'
      });

      e.items.push(new Item({
        index: 1,
        name: 'Chuck the Plant'
      }));
      e.items.push(new Item({
        index: 2,
        name: 'Hamster'
      }));
      e.items.push(new Item({
        index: 3,
        name: 'Tentacle Chow'
      }));

      $scope.boxes.push(e);

    };

    this.init();

  });

  app.directive("sortable", ["$timeout", function($timeout) {
    return {
      template: '<div class="sortable" ng-transclude></div>',
      transclude: true,
      scope: {
        'handle': '@'
      },
      link: function(scope, element, attrs) {

        $timeout(function() {
          //console.log(element)

          var sortable = element.find('> div');
          console.log(sortable[0]);

          scope.sortable = Sortable.create(sortable[0], {
            handle: scope.handle || null
          });
        });
      }
    };
  }]);

}());


function Box(args) {
  this.name = args.name || null;
  this.items = [];
}

function Item(args) {
  this.index = args.index || null;
  this.name = args.name || null;
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <link rel="stylesheet" href="style.css" />
  <style>
  .container {
    border: 1px solid #929292;
    padding: 5px;
  }

  .header {
    font-size: 1.2rem;
    padding: 10px 15px;
    background-color: #F5F5F5;
    border-bottom: 2px solid #E2E2E2;
  }

  .body {
    background-color: #F2F2F2;
    padding: 10px 10px;
    margin-bottom: 10px;
  }

  .body .item {
    border: 1px solid #D2D2D2;
    padding: 5px;
    margin-bottom: 5px;
  }

  .body .options {
    float: right;
  }

  .body .options .delete {
    cursor: pointer;
  }

  .body .options .handle {
    cursor: move;
  }

  .debug {
    margin-top: 20px;
    border-top: 1px dotted #929292;
  }
</style>
</head>

<body>
  <div ng-app="myApp" ng-controller="myAppController as appCtrl">
    <div class="container">
      <div ng-repeat="box in boxes">
        <div class="header">{{ box.name }}</div>
        <div class="body">
          <div data-sortable="" data-handle=".handle">
            <div class="item" ng-repeat="item in box.items">
              {{item.index }}) {{ item.name }}
              <div class="options">
                <span ng-click="removeBoxItem(box, item)" class="delete">[X]</span>
                <span class="handle">[^]</span>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="debug">
        <pre>{{ boxes | json }}                    
          </pre>
      </div>
    </div>
  </div>
  <script data-require="jquery@3.1.1" data-semver="3.1.1" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
  <script data-require="Sortable.js@1.6.0" data-semver="1.6.0" src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.6.0/Sortable.js"></script>
  <script data-require="angular.js@1.6.6" data-semver="1.6.6" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.js"></script>
  <script src="script.js"></script>
</body>

</html>

我对此感到困惑,在我的真实代码中,事情变得更加破碎 - 我制作了一个围绕“Boxes”的可折叠指令,因此我可以一次打开和操作一个 - 在这种情况下将项目4移动到位置1并删除它会从视图中删除所有项目(但不会从$ scope中删除)。将新项添加到$ scope的数组会导致项正确地重新出现。现在我创建了更简单的版本,因为我猜这都是以某种方式连接的。

我知道sortable应该设置对象索引等但是现在我想了解发生了什么。我怀疑我在理解范围内发生了什么问题(?)。非常感谢任何帮助。

0 个答案:

没有答案