【问题标题】:Angularjs: how to revert back to the runtime loaded DOM elements in the previous view on going back (preserve state)Angularjs:如何在返回时恢复到上一个​​视图中运行时加载的DOM元素(保留状态)
【发布时间】:2014-04-19 15:59:03
【问题描述】:

我有一个 Angular 应用程序,它有两个视图:

1) 列表视图

2) 详细视图

当您从列表视图中单击缩略图时,您会转到详细视图,这是路线:

app.config(['$routeProvider',
  function($routeProvider) {
    $routeProvider.
      when('/list', {
        templateUrl: 'partials/list.html',
        controller: 'ListCtrl',

      }).
      when('/list/:id', {
        templateUrl: 'partials/detail.html',
        controller: 'DetailCtrl',

      }).
      otherwise({
        redirectTo: '/list'
      });
  }]);

现在'listCtrl'控制器中有一个函数loadmore用于加载

myControllers.controller('ListCtrl', ['$scope', '$location', 'Troll', '$http',

function ($scope, $location, Troll, $http) {
    $scope.Trolls = Troll.query();
    $scope.orderProp = 'popular';
    $scope.fromData = {};
    //console.log($scope.Trolls);
    //this will be used to fetch the data in json which is defined in services.js

    $scope.loadmore = function () {
        jQuery.ajax({
            url: 'trolls/trolls.php?troll_index=' + $('#main-content #item-list .sub-item').size(),
            type: 'GET',
            async: false,
            data: {},
            dataType: 'json',
            success: function (response) {


                if (response != null) {
                    $.each(response, function (index, item) {

                        $scope.Trolls.push({
                            UID: response[index].UID,
                            id: response[index].id,
                            popular: response[index].popular,
                            imageUrl: response[index].imageUrl,
                            name: response[index].name,
                            tags: response[index].tags,
                            category: response[index].category
                        });

                    });
                }
            },
            complete: function () {},
            error: function () {
                console.log('Failed!');
            }
        });
        $scope.text = 'Hello, Angular fanatic.';
        $http.get('trolls/trolls.php?troll_id=' + Troll);

    }

}]);

问题: 现在的问题是, 如果我转到详细视图并返回列表视图,单击 loadmore 后,我新加载的 div 不见了,我该如何保留它们??

【问题讨论】:

  • 你试过 Angular 的 $templateCache 吗? docs.angularjs.org/api/ng/service/$templateCache
  • 我读过 $templateCache 但它与我的问题有什么关系,你能用一些演示解释一下吗??
  • 您使用jQuery.ajax而不是$http的任何原因?
  • “新加载的 div 不见了”。 ajax 请求再次运行后,它们会返回吗?
  • 添加到@MichalCharemza 评论;你为什么要使用 jQuery?你已经有了 Angular!

标签: javascript angularjs savestate


【解决方案1】:

当您更改路由时,负责该路由的控制器会在路由加载时初始化,并在路由更改时销毁。所以你丢失数据的原因是控制器被重新初始化并且以前的数据永远不存在。

有两种方法可以解决此问题。

  1. 未销毁的更高级别控制器 - 可能存在于身体上 - 这会将其范围传递给子控制器。但这并不是真正的关注点模块化。对于这个问题...对于其他问题非常有用 - 身份验证、配置文件等。

  2. 我提倡的方法是将其拉入服务,例如 listService - 这将获取并缓存数据,并在重新加载时将其传递回 listController,从而防止数据丢失。


第一种解决方法可能是这样的......

因此,如果您有一个更高级别的控制器负责获取数据或将其移动到我会做的服务中,那么从 loadMore 函数加载的数据将继续存在,但它需要在路由更改时未销毁的更高父范围上。

HTML:

<body ng-controller="ApplicationController">
     <!-- Code Here -->
</body>

控制器:

myControllers.controller('ApplicationController', function($scope) {
     var data = [];

     $scope.loadmore = function () {
        // Use Angular here!!! $http not jQuery! 
        // Its possible to write a complete Angular app and not ever true jQuery
        // jQuery Lite the Angular implementation will be used though
        jQuery.ajax({
            url: 'trolls/trolls.php?troll_index=' + $('#main-content #item-list .sub-item').size(),
            type: 'GET',
            async: false,
            data: {},
            dataType: 'json',
            success: function (response) {


                if (response != null) {
                    $.each(response, function (index, item) {

                        data.push({
                            UID: response[index].UID,
                            id: response[index].id,
                            popular: response[index].popular,
                            imageUrl: response[index].imageUrl,
                            name: response[index].name,
                            tags: response[index].tags,
                            category: response[index].category
                        });

                    });
                }

                return data;

            }
            error: function () {
                console.log('Failed!');
            }
        });

    }
});

但是我不太喜欢这种方法,因为它有点 hacky...并且使用了 jQuery...

使用服务获取/缓存的第二种方法:

因此,让我们将其拉入服务中。

myServices.factory('listService', function($http, $q) {

   var//iable declaration 
      service = {},
      list = []
   ;
   /////////////////////   
   //Private functions//
   /////////////////////

   function loadMore(url) {
      var deferred = $q.defer();

      $http({ method: 'GET', url: url }) // Need to pass in the specific URL maybe from the DOM scoped function?
      .success(function(data) {
         deferred.resolve(data);
      })
      .error(function() {
        deferred.reject();
        //Do error things
      });   

     return deferred.promise; 
   }

   ////////////////////
   //Public Functions//
   ////////////////////

   service.loadMore = function(url) { 
      // Used for loading more data
      loadMore(url).then(function(data) {
        list.push(data);
        return list
      });
   }

   service.getList = function() {
      // Returns the currently loaded data
      return list;
   }

 return service;

});

然后在你的控制器中:

myControllers.controller('ListCtrl', ['$scope', '$location', 'Troll', listService

function ($scope, $location, Troll, listService) {
    $scope.Trolls = Troll.query();
    $scope.orderProp = 'popular';
    $scope.fromData = {};


    $scope.loadmore = function(subItemSize) { //add url specific params here
       var url = 'trolls/trolls.php?troll_index=' + subItemSize;
       return listService.loadMore(url);
    };

}]);

【讨论】:

  • 在实现服务方法时出现此错误:[$injector:unpr] 未知提供者:listServiceProvider
  • 您需要将其添加为模块依赖示例您添加 myController 的地方
  • 我对此表示赞同,但想指出选项 2 可能是最好的选择。
  • @BrianGlick 我同意,也在帖子中说明。
  • 如何保留 DOM 元素,例如当用户返回该路线时应保持其缩放/平移状态的 Google 地图?抄送@BrianGlick。
【解决方案2】:

使用 ui-router 代替: https://github.com/angular-ui/ui-router,你可以有多个ui-view,也可以使用相对路由,你应该定义子状态,这样当路由变为子状态时父状态保持不变,看看这个视频:https://egghead.io/lessons/angularjs-introduction-ui-router

我创建了一个 plunker:http://plnkr.co/edit/FA3DuHgngKD2CIPG5bHW?p=preview

【讨论】:

  • @StenMuchow 如果您的列表视图是 ui.router 父状态,而详细视图是子状态,则进入详细视图(然后返回)不会破坏或重新初始化列表。
  • @MichalCharemza 我同意,但是当我评论这篇文章时,它没有包含更新的信息。
  • 对不起,伙计们,我已经尝试了你提到的所有方法,但似乎没有一个适合我。
  • @Alex - 你遇到了什么问题?还是喷油器错误?
  • 我会使用这种方法。 UI-Router 非常适合基于状态的视图。
【解决方案3】:

您可以将数据存储在服务中或将其缓存到 Angular 缓存中,但是当您路由回该视图时,您的 div 仍然会消失。

如果你也想保留 DOM 的状态ui-router 有一个扩展名为 ui-router-extras。它有一个很好的演示,在选项卡之间切换时状态转换和完整的 DOM 保存。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-20
    • 1970-01-01
    • 1970-01-01
    • 2017-08-14
    • 1970-01-01
    相关资源
    最近更新 更多