AngularJS:使用不同的控制器保持不同视图之间的视图状态

AngularJS : Keep view state between differents views with differents controllers

本文关键字:视图 之间 视图状态 控制器 AngularJS      更新时间:2023-09-26

我的角度应用程序从/home 状态启动(我使用 ui-router ),它有自己的控制器,在其中我调用工厂方法从我的 API 中获取一些 json 对象,这要归功于整个应用程序之间的这个工厂。我把我从中得到的列表放在/home 状态的$scope对象中。

我想做的是只调用工厂的这个 init 方法一次,更好的是只调用一次/home 控制器。

实际上,当我转到另一个状态(如/about)时,当我返回到/home 时,会再次调用/home 控制器,工厂的 init 方法也是如此。那么如何保持初始视图状态呢?

材料工厂.js :

app.factory('StuffFactory', function ($window, $http, $q) {
var stuffs;
return {
    initStuffsList: function () {
        return $http.get('http://myapi/stuff/init')
                .then(function (response) {
                    stuffs = (angular.fromJson(response.data.result));
                });

    },
    getStuffs: function () {
        return stuffs;
    }
};

});

首页控制器.js :

app.controller('homeCtrl', function ($scope,StuffFactory) {

StuffFactory.initStuffsList().then(function(){
         $scope.stuffs = StuffFactory.getStuffs();
       });
});

应用程序.js :

        .config(['$stateProvider', '$urlRouterProvider']

            $urlRouterProvider.otherwise('/home');
            $stateProvider

                    .state('home', {
                        url: '/home',
                        templateUrl: './partials/home.html',
                        controller:homeCtrl
                        })
                        .state('about', {
                            url: '/about',
                            templateUrl: './partials/about.html',
                            controller:aboutCtrl
                        })

工厂是单例,因此您可以在工厂中进行一次性初始化,只需返回来自initStuffsList的承诺。现在初始化只发生一次,但您的控制器仍然可以确保它至少发生一次。

app.factory('StuffFactory', function ($window, $http, $q) {
    var stuffs;
    var initialised = $http.get('http://myapi/stuff/init')
        .then(function (response) {
             return stuffs = (angular.fromJson(response.data.result));
         });
    return {
        initStuffsList: function () {
            return initialised;
        },
        getStuffs: function () {
            return stuffs;
        }
    };
});

控制器保持不变:

app.controller('homeCtrl', function ($scope,StuffFactory) {
StuffFactory.initStuffsList().then(function(){
         $scope.stuffs = StuffFactory.getStuffs();
       });
});

另请注意,您可以将初始化代码中的值直接返回给控制器,因此使用我在上面插入的return,这也将起作用:

app.controller('homeCtrl', function ($scope,StuffFactory) {
StuffFactory.initStuffsList().then(function(stuffs){
         $scope.stuffs = stuffs;
       });
});

尝试这样的事情:

服务:

app.factory('StuffFactory', function ($http, $q) {
  var _stuffs; // cache stuffs
  return {
    getStuffs: function () {
      if (_stuffs) {
        return $q.when(_stuffs);
      }
      return $http.get('http://myapi/stuff/init').then(function (response) {
        _stuffs = (angular.fromJson(response.data.result));
        return _stuffs;
      });
    }
  };
});

控制器 A 和 B:

StuffFactory.getStuffs().then(function(stuffs){
  $scope.stuffs = stuffs;
});

第二次调用该方法时,您将getStuffs()从缓存中获取数据。

一个简单的解决方案是另一个包装状态:

.state('home', {
    template: '<ui-view></ui-view>',
    controller: homeCtrl,
    abstract: true
})
.state('home.index', {
    templateUrl: './partials/home.html'
})
.state('home.about', {
    templateUrl: './partials/about.html',
    controller: aboutCtrl
})

这样home是两个状态的父状态,只要您处于任何home.状态,其控制器将只加载一次并保持活动状态。