3

我同时有一个带有两个控制器的页面布局,一个将数据显示为一种侧面导航,基于存储在浏览器本地存储中的数据和至少一个绑定到路由和视图的其他控制器。

我在下面创建了这个小线框图形,它显示了页面布局:

示例图像两个控制器

第二个控制器用于操作本地存储的数据并执行添加新项目或删除现有项目等操作。我的目标是保持数据同步,如果一个项目被“ManageListCrtl”添加或删除,使用“ListCtrl”的侧边导航应该立即更新。

我通过将本地存储逻辑分离到一个服务中来归档它,该服务在列表被操纵时执行广播,每个控制器监听这个事件并更新作用域的列表。

这很好用,但我不确定是否有最佳做法。

这是我的代码的精简版本,仅包含必要的部分:

angular.module('StoredListExample', ['LocalObjectStorage'])
    .service('StoredList', function ($rootScope, LocalObjectStorage) {
        this.add = function (url, title) {
            // local storage add logic

            $rootScope.$broadcast('StoredList', list);
        };

        this.delete = function (id) {
            // local storage delete logic

            $rootScope.$broadcast('StoredList', list);
        };

        this.get = function () {
            // local storage get logic
        };
    });

angular.module('StoredListExample')
    .controller('ListCtrl', function ($scope, StoredList) {
        $scope.list = StoredList.get();

        $scope.$on('StoredList', function (event, data) {
            $scope.list = data;
        });
    });

angular.module('StoredListExample')
    .controller('ManageListCtrl', function ($scope, $location, StoredList) {
        $scope.list = StoredList.get();

        $scope.add = function () {
            StoredList.add($scope.url, $scope.title);
            $location.path('/manage');
        };

        $scope.delete = function (id) {
            StoredList.delete(id);
        };

        $scope.$on('StoredList', function (event, data) {
            $scope.list = data;
        });
    });
4

2 回答 2

2

我不认为这样做有什么问题。当然,您的另一个选择是将 $rootScope 注入到控制器和它们之间的 pub/sub 中,并带有 $rootScope.$broadcast 和 $rootScope.$on。

angular.module('StoredListExample')
.controller('ListCtrl', function ($scope, $rootScope) {
    $scope.list = [];

    $rootScope.$on('StoredList', function (event, data) {
        $scope.list = data;
    });
});

angular.module('StoredListExample')
.controller('ManageListCtrl', function ($scope, $rootScope, $location) {
    $scope.list = [];

    $scope.add = function () {
        //psuedo, not sure if this is what you'd be doing...
        $scope.list.push({ url: $scope.url, title: $scope.title});
        $scope.storedListUpdated();
        $location.path('/manage');
    };

    $scope.delete = function (id) {
        var index = $scope.list.indexOf(id);
        $scope.list.splice(index, 1);
        $scope.storedListUpdated();
    };

    $scope.storedListUpdated = function () {
        $rootScope.$broadcast('StoredList', $scope.list);
    };
});

此外,您可以通过拥有一个通用的父控制器以一种混乱但有趣的方式实现这一点。因此,您可以将“ManageListCtrl”中的“StoredListUpdated”事件发送到父控制器,然后父控制器会将相同的事件向下广播到“ListCtrl”。这将允许您避免使用 $rootScope,但是当您以这种方式添加更多事件时,它会在可读性方面变得非常混乱。

于 2013-06-21T23:04:11.620 回答
1

使用作为单例的通用服务在 2 个控制器之间共享数据始终是一种更好的做法 - 只需确保您仅使用引用,而不是在其中一个控制器中创建本地对象,该控制器实际上应该在服务中

于 2016-03-13T07:24:07.423 回答