Два массива, клонированных с Lodash, отдельные, но одинаковые.Зачем? - PullRequest
0 голосов
/ 23 декабря 2018

Я точно знаю, что здесь есть кое-что совершенно очевидное, что я полностью упускаю, поэтому ваша помощь очень ценится.

У меня есть функция, которая обеспечивает два раскрывающихся списка.Они содержат одни и те же данные (функция позволяет торговать между двумя людьми, люди - это данные), но я хочу, чтобы каждый из них получал свою копию указанных данных.

Другая часть этой функции заключается в том, чтоПри выборе Персона А в первом раскрывающемся списке я хочу отключить Персона А во втором раскрывающемся списке, и наоборот, поэтому у меня есть тег ng-options, обращающий внимание на свойство disabled объекта.

у меня есть проблема, что даже при использовании метода, такого как clone Лодаша, для правильного создания «нового» массива при первом назначении, каждый раз, когда я обращаюсь к Person A в ОДНОМ массиве (и, в частности, НЕ обращаюсь к другому массиву), неизменно яЯ вижу, что когда я прикасаюсь к Персоне А, этот объект обновляется в ОБОИХ массивах, что приводит меня в замешательство.

Это похоже на неуклюжую, непростую проблему с Javascript (стандартный PEBCAK, мне кажется,Я явно недопонимаю или просто пропускаю что-то фундаментальное), может быть, с небольшим количеством связанной с рендерингом забавы AngularJS, но ...Что дает?

angular.module('myApp', [])
  .controller('weirdDataController', function($scope) {
    $scope.$watch('manager1_id', () => {
      if (angular.isDefined($scope.manager1_id) && parseInt($scope.manager1_id, 10) > 0) {
        $scope._disableManagerInOtherDropdown(false, $scope.manager1_id);
      }
    });

    $scope.$watch('manager2_id', () => {
      if (angular.isDefined($scope.manager2_id) && parseInt($scope.manager2_id, 10) > 0) {
        $scope._disableManagerInOtherDropdown(true, $scope.manager2_id);
      }
    });

    $scope._gimmeFakeData = () => {
      return [{
          manager_id: 1,
          manager_name: 'Bill',
          disabled: false
        },
        {
          manager_id: 2,
          manager_name: 'Bob',
          disabled: false
        },
        {
          manager_id: 3,
          manager_name: 'Beano',
          disabled: false
        },
        {
          manager_id: 4,
          manager_name: 'Barf',
          disabled: false
        },
        {
          manager_id: 5,
          manager_name: 'Biff',
          disabled: false
        },
      ];
    };

    const data = $scope._gimmeFakeData();
    $scope.firstManagers = _.clone(data);
    $scope.secondManagers = _.clone(data);

    $scope._disableManagerInOtherDropdown = (otherIsFirstArray, managerId) => {
      const disableManagers = manager => {
        manager.disabled = manager.manager_id === managerId;
      };

      if (otherIsFirstArray) {
        $scope.firstManagers.forEach(disableManagers);
      } else {
        $scope.secondManagers.forEach(disableManagers);
      }

      console.log('Is the first item the same??', $scope.firstManagers[0].disabled === $scope.secondManagers[0].disabled);
    }
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="myApp" ng-controller="weirdDataController">
  <div class="col-xs-12 col-sm-6">
    <select class="form-control" ng-model="manager1_id" ng-options="manager.manager_id as manager.manager_name disable when manager.disabled for manager in firstManagers track by manager.manager_id">
      <option value="" disabled="disabled">Choose one manager</option>
    </select>
    <select class="form-control" ng-model="manager2_id" ng-options="manager.manager_id as manager.manager_name disable when manager.disabled for manager in secondManagers track by manager.manager_id">
      <option value="" disabled="disabled">Choose another manager</option>
    </select>
  </div>
</div>
<br /><br />

Я добавил все, что нужно, на $scope только для того, чтобы заставить его работать и проиллюстрировать проблему, но вот как это происходит:

  • При инициализации я беру массив, а затем клонирую копию для каждого раскрывающегося списка
  • Когда каждый раскрывающийся список изменяет свойство модели (идентификатор объекта), у меня есть прослушиватель области действия, затем вызываю метод для обработки отключениявыбранный объект / персона в списке OPPOSITE
  • В этом методе я определяю, какой из двух списков / массивов следует перебрать, и помечаю отключенный объект
  • . В конце этого метода ясделать простой вызов console.log, чтобы проверить значение данного объекта.Для простоты и простоты я просто беру элемент с индексом 0.
  • То, что я ожидал: у одного объекта значение disabled равно true, а у противоположного объекта значение false.Что я вижу: у них обоих true (при условии, что вы выбираете первый "настоящий" элемент в выпадающем списке)

В чем же дело?Насколько я большой идиот?

1 Ответ

0 голосов
/ 19 января 2019

Ответ на мой вопрос был следующим: clone() не выполняет "глубокий" клон по умолчанию, поэтому я имел дело с тем же массивом, несмотря на неудачную попытку, которой я не был.Использование метода cloneDeep() Лодаша решило мою проблему, но, как предложил Патрик, я переоценил то, как написал соответствующий метод, и реорганизовал его, что исключило необходимость вообще использовать любое клонирование.

...