更新angular.js服务对象,无需扩展/复制

Updating angular.js service object without extend/copy possible?

本文关键字:扩展 复制 angular js 服务 对象 更新      更新时间:2023-09-26

我有两个服务,想从第二个服务更新第一个服务中的一个变量。在控制器中,我将范围变量设置为第一个服务的getter。

问题是,当服务变量发生变化时,连接到控制器的视图不会更新,除非我使用angular.extend/copy。看起来我应该可以在下面设置selectedBuilding,而不必使用extend/copy。是我做错了什么,还是你必须这样做?

控制器

app.controller('SelectedBuildingCtrl', function($scope, BuildingsService) {
    $scope.building = BuildingsService.getSelectedBuilding();    
});

服务1

app.factory('BuildingsService', function() {
    var buildingsList = [];
    var selectedBuilding = {};
    // buildingsList populated up here
    ...
    var setSelectedBuilding = function(buildingId) {
        angular.extend(selectedBuilding, _.find(
            buildingsList, {'building_id': buildingId})
        );
    };
    var getSelectedBuilding = function() {
        return selectedBuilding;
    };
    ...
    return {
        setSelectedBuilding: setSelectedBuilding,
        getSelectedBuilding: getSelectedBuilding    
    }
});

服务2

app.factory('AnotherService', function(BuildingsService) {
    ...
    // something happens, gives me a building id
    BuildingsService.setSelectedBuilding(building_id);
    ...
});

提前感谢!

执行此代码时:

$scope.building = BuildingsService.getSelectedBuilding(); 

$scope.building复制的,是对内存中与服务的selectedBuilding相同的对象的引用。将另一个对象分配给selectedBuilding时,$scope.building仍然引用旧对象。这就是为什么视图没有更新,而您必须使用angular.copy/extend

如果您需要为selectedBuilding:分配新对象,可以尝试以下解决方案来避免此问题

app.factory('BuildingsService', function() {
        var buildingsList = [];
        var building = { //create another object to **hang** the reference
            selectedBuilding : {}
         }
        // buildingsList populated up here
        ...
        var setSelectedBuilding = function(buildingId) {
            //just assign a new object to building.selectedBuilding 
        };
        var getSelectedBuilding = function() {
            return building; //return the building instead of selectedBuilding 
        };
        ...
        return {
            setSelectedBuilding: setSelectedBuilding,
            getSelectedBuilding: getSelectedBuilding    
        }
    });

使用此解决方案,您必须更新视图以替换$scope.building$scope.building.selectedBuilding的绑定。

在我看来,我将坚持使用angular.copy/extend来避免这种不必要的复杂性。

我认为您的服务不需要扩展。您应该能够直接观看服务并对更改做出响应:

app.controller('SelectedBuildingCtrl', function($scope, BuildingsService) {
  // first function is evaluated on every $digest cycle
  $scope.$watch(function(scope){
    return BuildingsService.getSelectedBuilding();
  // second function is a callback that provides the changes
  }, function(newVal, oldVal, scope) {
    scope.building = newVal;
  }
});

$watch上的更多信息:https://code.angularjs.org/1.2.16/docs/api/ng/type/$rootScope.Scope