离子列表在调用 $state.go 后不刷新

ion-list does not refresh after $state.go is called

我正在使用本教程学习 AngularJS 和离子框架:

http://www.htmlxprs.com/post/12/tutorial-on-using-parse-rest-api-and-ionic-framework-together

一切正常,直到我在 createTodo 状态下创建一个新项目然后调用 $state.go('todos') 返回到我的项目列表,这里是代码对于创建 Todo 控制器:

.controller('TodoCreateController', ['$scope', 'Todo', '$state', function($scope, Todo, $state) {
    $scope.todo = {};

    $scope.create = function() {
        Todo.create({content: $scope.todo.content}).success(function(data) {
            $state.go('todos', {}, {reload: true});
        });
    }
}])

这是项目列表控制器的代码:

.controller('TodoListController', ['$scope', 'Todo', '$state', function($scope, Todo) {
    Todo.getAll().success(function(data) {
        $scope.items = data.results;
    });

    $scope.deleteItem = function(item) {
        Todo.delete(item.objectId);
        $scope.items.splice($scope.items.indexOf(item), 1);
    };
}])

这是配置的状态

.config(function($stateProvider) {
    $stateProvider.state('todos', {
        url: '/todos',
        controller: 'TodoListController',
        templateUrl: 'views/todos.html'
    }).state('createTodo', {
        url: '/todo/new',
        controller: 'TodoCreateController',
        templateUrl: 'views/create-todo.html'
    });
})

当应用程序启动时,TodoListController 的方法被调用,这要归功于添加的最后一行和主程序中 .run 方法的结尾 app.js(或者至少这是我的理解):

.run(function($ionicPlatform, $state) {
    $ionicPlatform.ready(function() {

        if(window.cordova && window.cordova.plugins.Keyboard) {
            cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
        }
        if(window.StatusBar) {
            StatusBar.styleDefault();
        }
    });

    $state.go('todos');
})

我的问题是,一旦创建了新项目并且我从 TodoCreateController 调用了 $state.go('todos') ,它会将我带回到项目列表,但是新项目不存在并且永远不会调用 TodoListController 的方法,因此列表已过时。

如何在创建新项目后刷新处于'todos'状态的列表?

我的建议:

在您的配置中添加:

$stateProvider.state('todos', {
    url: '/todos',
    controller: 'TodoListController',
    templateUrl: 'views/todos.html',
    params : {
        updated : false
    }
})

阅读有关 ui-路由器的参数 here

然后在你创建的待办事项的 $state.go 中,我会将其更改为:

$scope.create = function() {
    Todo.create({content: $scope.todo.content}).success(function(data) {
        $state.go('todos', {updated: true});
    });
}

我会在你的待办事项控制器中添加这个

if($stateParams.updated == true){
    Todo.getAll().success(function(data) {
        $scope.items = data.results;
    });
    $stateParams.updated = false;
}

这种方式而不是指望重新加载到 运行 您正在明确寻找将触发重新加载的值的函数。您也可以使用 data 对象而不是 params 对象和 set/retrieve 值来做同样的事情:

$state.get('createTodo').data.updated = true;
if($state.current.data.updated == true);

希望对您有所帮助!

另一个想法

向混音中添加状态更改侦听器:

$rootScope.$on('$stateChangeSuccess', function(e, toState, toParams, fromState, fromParams) {
    if(fromState.name === 'createTodo' && toParams.updated == true){
        Todo.getAll().success(function(data) {
            $scope.items = data.results;
        });
        $stateParams.updated = false;
    }
}

我找到了一个相当优雅的解决方案:

在我的 TodoListController 中,我定义了一个事件监听器,如下所示:

$rootScope.$on('todo:listChanged', function() {
    $scope.updateList();
});

然后是 updateList() 方法

$scope.updateList = function() {
    Todo.getAll().success(function(data) {
        $scope.items = data.results;
    });
};

最后,在 TodoCreateController 中,我在项目创建后立即向上发出事件,就在更改状态之前

$scope.create = function() {
    Todo.create({content: $scope.todo.content}).success(function(data) {
        $scope.$emit('todo:listChanged');
        $state.go('todos');
    });
};

瞧!列表相应地更新,如果我删除或更新列表项,我现在可以使用相同的事件

这对我有用:

$state.transitionTo('new-state', $state.$current.params, {reload: true});

我遇到过这个问题和类似的问题,结果证明 离子视图缓存 通常是返回缓存视图时不调用控制器代码的原因。

可能的解决方案

将控制器代码分成一次性初始化代码运行进入视图时,通常会结束控制器看起来像这样:

// one-time initialization
$scope.updateList = function() {
    Todo.getAll().success(function(data) {
        $scope.items = data.results;
    });
};

$scope.$on('$ionicView.beforeEnter', function () {
    $scope.updateList();
});

这应该可以解决您的问题,而无需触发事件或向路由添加参数或数据。

备选

可以通过不同的方式禁用视图缓存:

  • cache: false添加到状态定义
  • cache-view="false"添加到html <ion-view ...>
  • 使用 $ionicConfigProvider.views.maxCache(0); 禁用缓存(不推荐这样做)

使用子状态时的陷阱

不是你的情况,但如果 子状态 中的 editing/creating 行(例如,状态 todotodo.create创建一个新的待办事项),ui-路由器还有一个问题:

当从todo.create导航到状态todo时,你的超状态todo不会是"executed",因为你来的时候已经处于这个状态来自 todo.create。这是一个常见问题,可以通过对此 post.

的其他答案中提供的更复杂的解决方案之一来解决。