在AngularJS中,您可以在不重新加载控制器的情况下更改路径吗?
以前有人问过这个问题,从答案来看不太好。我想在考虑这个示例代码时询问 我的应用程序在提供它的服务中加载当前项目。有几个控制器可以在不重新加载项目的情况下操作项目数据 如果项目尚未设置,“我的控制器”将重新加载该项目,否则,它将在控制器之间使用当前从服务加载的项目 问题:我希望在不重新加载Item.html的情况下为每个控制器使用不同的路径 1) 可能吗 2) 如果这是不可能的,那么与我在这里提出的方法相比,有没有更好的方法让每个控制器都有一个路径 app.js在AngularJS中,您可以在不重新加载控制器的情况下更改路径吗?,angularjs,Angularjs,以前有人问过这个问题,从答案来看不太好。我想在考虑这个示例代码时询问 我的应用程序在提供它的服务中加载当前项目。有几个控制器可以在不重新加载项目的情况下操作项目数据 如果项目尚未设置,“我的控制器”将重新加载该项目,否则,它将在控制器之间使用当前从服务加载的项目 问题:我希望在不重新加载Item.html的情况下为每个控制器使用不同的路径 1) 可能吗 2) 如果这是不可能的,那么与我在这里提出的方法相比,有没有更好的方法让每个控制器都有一个路径 app.js var-app=angular.m
var-app=angular.module('myModule',[])。
配置(['$routeProvider',函数($routeProvider){
$routeProvider。
when('/items',{templateUrl:'partials/items.html',controller:ItemsCtrl})。
当('/items/:itemId/foo',{templateUrl:'partials/item.html',controller:ItemFooCtrl})时。
当('/items/:itemId/bar',{templateUrl:'partials/item.html',controller:ItemBarCtrl})时。
否则({重定向到:'/items'});
}]);
Item.html
controller.js
//刷新或直接链接时加载$scope.item的Helper函数
函数itemCtrlInit($scope、$routeParams、MyService){
$scope.item=MyService.currentItem;
如果(!$scope.item){
MyService.currentItem=MyService.get({itemId:$routeParams.itemId});
$scope.item=MyService.currentItem;
}
}
函数itemFooCtrl($scope、$routeParams、MyService){
$scope.view={name:'foo',template:'partials/itemFoo.html'};
itemCtrlInit($scope、$routeParams、MyService);
}
函数itemBarCtrl($scope、$routeParams、MyService){
$scope.view={name:'bar',template:'partials/itemBar.html'};
itemCtrlInit($scope、$routeParams、MyService);
}
分辨率。
$location.path('/edit_draft_inbox/'+id, false);
状态:使用已接受答案中建议的搜索查询,可以在不重新加载主控制器的情况下提供不同的URL
app.js
var-app=angular.module('myModule',[])。
配置(['$routeProvider',函数($routeProvider){
$routeProvider。
when('/items',{templateUrl:'partials/items.html',controller:ItemsCtrl})。
当(“/item/:itemId/”,{templateUrl:'partials/item.html',controller:ItemCtrl,reloadOnSearch:false})时。
否则({重定向到:'/items'});
}]);
Item.html
controller.js
function ItemCtrl($scope、$routeParams、Appts){
$scope.views={
foo:{name:'foo',template:'partials/itemFoo.html'},
bar:{name:'bar',template:'partials/itemBar.html'},
}
$scope.view=$scope.views[$routeParams.view];
}
指令.js
app.directive('itemTab',function(){
返回函数(范围、元素、属性){
范围.$watch(attrs.itemTab,函数(val){
if(val+'Tab'==attrs.id){
元素addClass(“活动”);
}否则{
元素移除类(“活动”);
}
});
}
});
如果您不必使用像
#/item/{{item.id}/foo
和#/item/{item.id}/bar
这样的URL,我的分区中的内容将用ng controller=…
包装,但是#/item/{item.id}/{foo
和/item/{item.id}/bar/{code>可以为您的项目设置路由/
将重新加载搜索设置为false
()。这告诉AngularJS,如果url的搜索部分发生变化,就不要重新加载视图。尽管这篇文章很旧,并且已经有了一个被接受的答案,但对于我们这些需要更改实际路径而不仅仅是参数的人来说,使用reloadOnSeach=false并不能解决问题。下面是一个简单的解决方案:
使用ng include而不是ng view,并在模板中指定控制器
<!-- In your index.html - instead of using ng-view -->
<div ng-include="templateUrl"></div>
<!-- In your template specified by app.config -->
<div ng-controller="MyController">{{variableInMyController}}</div>
//in config
$routeProvider
.when('/my/page/route/:id', {
templateUrl: 'myPage.html',
})
//in top level controller with $route injected
$scope.templateUrl = ''
$scope.$on('$routeChangeSuccess',function(){
$scope.templateUrl = $route.current.templateUrl;
})
//in controller that doesn't reload
$scope.$on('$routeChangeSuccess',function(){
//update your scope based on new $routeParams
})
{{variableInMyController}}
//在配置中
$routeProvider
.when('/my/page/route/:id',{
templateUrl:'myPage.html',
})
//在顶级控制器中注入$route
$scope.templateUrl=“”
$scope.$on(“$routeChangeSuccess”,函数(){
$scope.templateUrl=$route.current.templateUrl;
})
//在不重新加载的控制器中
$scope.$on(“$routeChangeSuccess”,函数(){
//根据新的$routeParams更新您的范围
})
唯一的缺点是不能使用resolve属性,但这很容易解决。此外,您还必须管理控制器的状态,就像基于$routeParams的逻辑一样,当控制器内的路由随着相应url的更改而更改时
下面是一个示例:如果需要更改路径,请在应用程序文件中的.config之后添加此选项。
然后可以执行$location.path('/sampleurl',false)代码>以防止重新加载
app.run(['$route', '$rootScope', '$location', function ($route, $rootScope, $location) {
var original = $location.path;
$location.path = function (path, reload) {
if (reload === false) {
var lastRoute = $route.current;
var un = $rootScope.$on('$locationChangeSuccess', function () {
$route.current = lastRoute;
un();
});
}
return original.apply($location, [path]);
};
}])
我发现的最优雅的解决方案值得称赞。为什么不把ng控制器提高一级
<body ng-controller="ProjectController">
<div ng-view><div>
它适合我。适合那些需要在不重新加载控制器的情况下更改path()的人-
以下是插件:
用法:
$location.update_path('/notes/1');
基于
注意:此解决方案包含错误
调用路径(,false)后-它将中断浏览器的向后/向前导航,直到调用路径(,true)我使用此解决方案
angular.module('reload-service.module', [])
.factory('reloadService', function($route,$timeout, $location) {
return {
preventReload: function($scope, navigateCallback) {
var lastRoute = $route.current;
$scope.$on('$locationChangeSuccess', function() {
if (lastRoute.$$route.templateUrl === $route.current.$$route.templateUrl) {
var routeParams = angular.copy($route.current.params);
$route.current = lastRoute;
navigateCallback(routeParams);
}
});
}
};
})
//usage
.controller('noReloadController', function($scope, $routeParams, reloadService) {
$scope.routeParams = $routeParams;
reloadService.preventReload($scope, function(newParams) {
$scope.routeParams = newParams;
});
});
这种方法保留了后退按钮功能,并且与我见过的其他方法不同,模板中始终有当前路线图。以下是我的更全面的解决方案,它解决了@Vigrond和@rahilwazir遗漏的一些问题:
- 更改搜索参数时,将阻止广播
$routeUpdate
- 当路由实际上保持不变时,
$locationChangeSuccess
将不会触发,这将导致阻止下一次路由更新
- 如果在同一个摘要周期中有另一个更新请求,这次希望重新加载,则事件处理程序将取消该重新加载
app.run(['$rootScope', '$route', '$location', '$timeout', function ($rootScope, $route, $location, $timeout) {
['url', 'path'].forEach(function (method) {
var original = $location[method];
var requestId = 0;
$location[method] = function (param, reload) {
// getter
if (!param) return original.call($location);
# only last call allowed to do things in one digest cycle
var currentRequestId = ++requestId;
if (reload === false) {
var lastRoute = $route.current;
// intercept ONLY the next $locateChangeSuccess
var un = $rootScope.$on('$locationChangeSuccess', function () {
un();
if (requestId !== currentRequestId) return;
if (!angular.equals($route.current.params, lastRoute.params)) {
// this should always be broadcast when params change
$rootScope.$broadcast('$routeUpdate');
}
var current = $route.current;
$route.current = lastRoute;
// make a route change to the previous route work
$timeout(function() {
if (requestId !== currentRequestId) return;
$route.current = current;
});
});
// if it didn't fire for some reason, don't intercept the next one
$timeout(un);
}
return original.call($location, param);
};
});
}]);
.when('/:param1/:param2?/:param3?', {
templateUrl: 'home.html',
controller: 'HomeController',
controllerAs: 'vm',
noReload: true
})
fooRun.$inject = ['$rootScope', '$route', '$routeParams'];
function fooRun($rootScope, $route, $routeParams) {
$rootScope.$on('$routeChangeStart', function (event, nextRoute, lastRoute) {
if (lastRoute && nextRoute.noReload
&& lastRoute.controller === nextRoute.controller) {
var un = $rootScope.$on('$locationChangeSuccess', function () {
un();
// Broadcast routeUpdate if params changed. Also update
// $routeParams accordingly
if (!angular.equals($route.current.params, lastRoute.params)) {
lastRoute.params = nextRoute.params;
angular.copy(lastRoute.params, $routeParams);
$rootScope.$broadcast('$routeUpdate', lastRoute);
}
// Prevent reload of controller by setting current
// route to the previous one.
$route.current = lastRoute;
});
}
});
}
HomeController.$inject = ['$scope', '$routeParams'];
function HomeController($scope, $routeParams) {
//(...)
$scope.$on("$routeUpdate", function handler(route) {
// Do whatever you need to do with new $routeParams
// You can also access the route from the parameter passed
// to the event
});
//(...)
}
<script type="text/javascript">
angular.element(document.getElementsByTagName('head')).append(angular.element('<base href="' + window.location.pathname + '" />'));
</script>
URL is - http://localhost:9000/#/edit_draft_inbox/1457
$location.path('/edit_draft_inbox/'+id, false);
$location.path('/items');
$location.replace();
window.localStorage['routeChangeWithoutReloadTimestamp'] = new Date().getTime();
$location.path(myURL);
.when(myURL, {
templateUrl: 'main.html',
controller:'MainCtrl',
controllerAs: 'vm',
reloadOnSearch: false,
resolve:
{
var routeChangeWithoutReloadTimestamp =
window.localStorage['routeChangeWithoutReloadTimestamp'];
var currentTimestamp = new Date().getTime();
if (!routeChangeWithoutReloadTimestamp ||
currentTimestamp - routeChangeWithoutReloadTimestamp >= 5000) {
//initialization code here
}
//reset the timestamp to trigger initialization when needed
window.localStorage['routeChangeWithoutReloadTimestamp'] = 0;
}
});