AngularJS UI路由器 – 更改url,无需重新加载状态

目前我们的项目是使用默认的$routeProvider ,我使用这个“黑客”来更改url无需重新加载页面:

 services.service('$locationEx', ['$location', '$route', '$rootScope', function($location, $route, $rootScope) { $location.skipReload = function () { var lastRoute = $route.current; var un = $rootScope.$on('$locationChangeSuccess', function () { $route.current = lastRoute; un(); }); return $location; }; return $location; }]); 

并在controller

 $locationEx.skipReload().path("/category/" + $scope.model.id).replace(); 

我正在考虑用ui-routerreplacerouteProvider来嵌套路由,但不能在ui-routerfind它。

是否有可能 – 与angular-ui-router

为什么我需要这个? 我举个例子来解释一下:
clicking保存后,创build新类别的路线是/category/new我显示success-alert ,我想改变路线/category/new/caterogy/23 (23 – 是存储在db中的新项目的id)

只要你可以使用$state.transitionTo而不是$state.go$state.go内部调用$state.transitionTo但自动将选项设置为{ location: true, inherit: true, relative: $state.$current, notify: true } 。 你可以调用$state.transitionTo并设置notify: false 。 例如:

 $state.go('.detail', {id: newId}) 

可以被replace

 $state.transitionTo('.detail', {id: newId}, { location: true, inherit: true, relative: $state.$current, notify: false }) 

编辑:正如fraczbuild议它可以简单地是:

 $state.go('.detail', {id: newId}, {notify: false}) 

好的,解决 🙂 Angular UI路由器有这个新的方法,$ urlRouterProvider.deferIntercept() https://github.com/angular-ui/ui-router/issues/64

基本上是这样的:

 angular.module('myApp', [ui.router]) .config(['$urlRouterProvider', function ($urlRouterProvider) { $urlRouterProvider.deferIntercept(); }]) // then define the interception .run(['$rootScope', '$urlRouter', '$location', '$state', function ($rootScope, $urlRouter, $location, $state) { $rootScope.$on('$locationChangeSuccess', function(e, newUrl, oldUrl) { // Prevent $urlRouter's default handler from firing e.preventDefault(); /** * provide conditions on when to * sync change in $location.path() with state reload. * I use $location and $state as examples, but * You can do any logic * before syncing OR stop syncing all together. */ if ($state.current.name !== 'main.exampleState' || newUrl === 'http://some.url' || oldUrl !=='https://another.url') { // your stuff $urlRouter.sync(); } else { // don't sync } }); // Configures $urlRouter's listener *after* your custom listener $urlRouter.listen(); }]); 

我认为这种方法目前只包括在angular度ui路由器的版本,一个可选参数(这也是很好,顺便说一句)。 它需要从源代码克隆和构build

 grunt build 

文档也可以从源代码中获取

 grunt ngdocs 

(他们被内置到/ site目录)// README.MD中的更多信息

似乎有另一种方式来做到这一点,dynamic参数 (我没有使用)。 许多信贷nateabele。


作为一个旁注,这里是Angular UI路由器的$ stateProvider中的可选参数 ,我将它与上面的组合使用:

 angular.module('myApp').config(['$stateProvider', function ($stateProvider) { $stateProvider .state('main.doorsList', { url: 'doors', controller: DoorsListCtrl, resolve: DoorsListCtrl.resolve, templateUrl: '/modules/doors/doors-list.html' }) .state('main.doorsSingle', { url: 'doors/:doorsSingle/:doorsDetail', params: { // as of today, it was unclear how to define a required parameter (more below) doorsSingle: {value: null}, doorsDetail: {value: null} }, controller: DoorsSingleCtrl, resolve: DoorsSingleCtrl.resolve, templateUrl: '/modules/doors/doors-single.html' }); }]); 

这样做可以解决一个状态,即使其中一个参数丢失。 SEO是一个目的,另一个可读性。

在上面的例子中,我想把doorsSingle作为一个必需的参数。 不清楚如何定义这些。 它适用于多个可选参数,所以不是一个真正的问题。 讨论在这里https://github.com/angular-ui/ui-router/pull/1032#issuecomment-49196090

花了很多时间在这个问题上,这是我的工作

 $state.go('stateName',params,{ // prevent the events onStart and onSuccess from firing notify:false, // prevent reload of the current state reload:false, // replace the last record when changing the params so you don't hit the back button and get old params location:'replace', // inherit the current params on the url inherit:true }); 

这个设置解决了以下问题:

  • .../.../123更新URL时,不会调用训练控制器两次
  • 在导航到另一个状态时,训练控制器不再被调用

状态configuration

 state('training', { abstract: true, url: '/training', templateUrl: 'partials/training.html', controller: 'TrainingController' }). state('training.edit', { url: '/:trainingId' }). state('training.new', { url: '/{trainingId}', // Optional Parameter params: { trainingId: null } }) 

调用状态 (来自任何其他控制器)

 $scope.editTraining = function (training) { $state.go('training.edit', { trainingId: training.id }); }; $scope.newTraining = function () { $state.go('training.new', { }); }; 

培训控制员

 var newTraining; if (!!!$state.params.trainingId) { // new newTraining = // create new training ... // Update the URL without reloading the controller $state.go('training.edit', { trainingId : newTraining.id }, { location: 'replace', // update url and replace inherit: false, notify: false }); } else { // edit // load existing training ... } 

我做了这个,但在很久以前的版本:UI路由器的v0.2.10像这样的东西::

 $stateProvider .state( 'home', { url: '/home', views: { '': { templateUrl: Url.resolveTemplateUrl('shared/partial/main.html'), controller: 'mainCtrl' }, } }) .state('home.login', { url: '/login', templateUrl: Url.resolveTemplateUrl('authentication/partial/login.html'), controller: 'authenticationCtrl' }) .state('home.logout', { url: '/logout/:state', controller: 'authenticationCtrl' }) .state('home.reservationChart', { url: '/reservations/?vw', views: { '': { templateUrl: Url.resolveTemplateUrl('reservationChart/partial/reservationChartContainer.html'), controller: 'reservationChartCtrl', reloadOnSearch: false }, 'viewVoucher@home.reservationChart': { templateUrl: Url.resolveTemplateUrl('voucher/partial/viewVoucherContainer.html'), controller: 'viewVoucherCtrl', reloadOnSearch: false }, 'addEditVoucher@home.reservationChart': { templateUrl: Url.resolveTemplateUrl('voucher/partial/voucherContainer.html'), controller: 'voucherCtrl', reloadOnSearch: false } }, reloadOnSearch: false }) 

如果您只需要更改url,但是防止更改状态:

更改位置(如果要在历史logging中replace,请添加.replace):

 this.$location.path([Your path]).replace(); 

防止redirect到你的状态:

 $transitions.onBefore({}, function($transition$) { if ($transition$.$to().name === '[state name]') { return false; } }); 

我不认为你需要这个ui路由器。 可用于$ location服务的文档在第一段中说:“… $ location的变化反映到浏览器地址栏中”。 它稍后继续说:“它不能做什么?当浏览器URL被改变时,它不会导致整个页面重新加载。”

所以,考虑到这一点,为什么不简单地改变$ location.path(因为该方法是一个getter和setter),如下所示:

 var newPath = IdFromService; $location.path(newPath); 

该文档注意到path始终应该以正斜杠开始,但是如果缺less,则会添加它。