在Angular JS中更新URL而不重新渲染视图


79

我正在AngularJS中构建仪表板系统,但遇到通过设置URL的问题 $location.path

在我们的仪表板中,我们有一堆小部件。单击它们时,每个视图都会显示一个更大的最大化视图。我们正在尝试设置深层链接,以允许用户使用最大化的小部件链接到仪表板。

目前,我们有2条路线看起来像/dashboard/:dashboardId/dashboard/:dashboardId/:maximizedWidgetId

当用户最大化窗口小部件时,我们使用来更新url $location.path,但这会导致视图重新呈现。由于我们拥有所有数据,因此我们不想重新加载整个视图,我们只想更新URL。有没有一种方法可以设置url而不会导致视图重新呈现?

HTML5Mode设置为true


1
如果您希望数据能够在客户端的路由更改中幸免,为什么不将其推送到服务中呢?
2014年

Answers:


133

实际上,每次更改URL时都会呈现一个视图。这就是$ routeProvider在Angular中的工作方式,但是您可以将其maximizeWidgetId作为不重新渲染视图的querystring传递。

App.config(function($routeProvider) {
  $routeProvider.when('/dashboard/:dashboardId', {reloadOnSearch: false});
});

单击窗口小部件以最大化时:

<a href="#/dashboard/1?maximizeWidgetId=1">Maximum This Widget</a>
or
$location.search('maximizeWidgetId', 1);

地址栏中的网址将更改为 http://app.com/dashboard/1?maximizeWidgetId=1

您甚至可以查看URL中的搜索发生了什么变化(从一个小部件到另一个小部件)

$scope.$on('$routeUpdate', function(scope, next, current) {
   // Minimize the current widget and maximize the new one
});

1
如果可以接受,我将创建一个单独的问题,不包含任何“:param”内容。只是一个愚蠢的问题:如何不重新渲染视图。
OZ_

2
在这种情况下,我认为angular-ui-router将是一个显而易见的选择。
2013年

1
我正在使用$routeUpdate活动。我认为$routeChangeStart移动到另一个位置时会触发获取。
lucassp

@kuchumovn:不幸的是,我们仍然在2014年。Angular 2.0将进行改进的路由(可能是内置的angular-ui-router),可以满足您的预期。
codef0rmer 2014年

1
@ codef0rmer,我已经多次找到了这个答案。谢谢!好的答案,毕竟还是这个时候!
2015年

9

您可以将$ routeProvider的reloadOnSearch属性设置为false。

可能重复的问题:是否可以更改路径而无需在AngularJS中重新加载控制器?

问候


看起来像是重复的。不幸的是,只要刷新是url路径(而不是查询变量)的一部分,它们似乎就会遇到相同的问题。
伊恩·缪尔

不,不是重复的。
OZ_

它不是重复的,因为链接的问题是关于不重新加载控制器,这是关于不重新加载模板。链接问题中的解决方案将重新加载视图。
Lajos Meszaros


3

在类似情况下,我们使用Angular UI Router而不是内置路由。似乎并没有重新实例化控制器并重新渲染整个视图。


2
您是否尝试过使用$state.transitionTo()而不是$location.path()
DreamSonic

1
我根本不更改$ location.path(),那应该写在哪里$state.transitionTo()
OZ_

Quote:“当用户最大化小部件时,我们使用location.path更新URL,但这会导致视图重新呈现。” 而不是更改路径,您应该调用$state.transitionTo(),这将依次更新url哈希。
DreamSonic

这个想法是,您应该有两种嵌套状态:一种用于您的仪表板,另一种用于最大化的小部件。当您从父状态导航到子状态时,将仅重新渲染子视图,而不是父视图。
DreamSonic

3

我意识到这是一个古老的问题,但是由于花了我一天半的时间才能找到答案,所以这里是。

如果使用angular-ui-router,无需将路径转换为查询字符串

当前,由于可能被认为是错误reloadOnSearch: false在状态上进行设置将导致无需重新加载视图即可更改路线。GitHub用户lmessinger甚至足够友善地提供它的演示。您可以从上面链接的他的评论中找到链接。

基本上,您需要做的是:

  1. 使用ui-router代替ngRoute
  2. 在您的州,声明您想要的 reloadOnSearch: false

在我的应用程序中,我有一个类别列表视图,您可以使用以下状态从该视图进入另一个类别:

$stateProvider.state('articles.list', {
  url: '{categorySlug}',
    templateUrl: 'partials/article-list.html',
    controller: 'ArticleListCtrl',
    reloadOnSearch: false
  });

而已。希望这可以帮助!


2

我的实现方式:(
我的解决方案主要用于需要更改整个路线而不是子部分的情况)

我有带菜单的页面(menuPage),不应在导航中清除数据(每页上都有很多输入,如果数据意外消失,用户将非常不满意)。

  1. 关闭$ routeProvider
  2. 在mainPage控制器中,添加两个具有自定义指令属性的div-每个指令仅包含“ templateUrl”和“ scope:true”

     <div ng-show="tab=='tab_name'" data-tab_name-page></div>
    
  3. mainPage控制器包含模拟路由的行:

    if (!$scope.tab && $location.path()) {
        $scope.tab = $location.path().substr(1);
    }
    $scope.setTab = function(tab) {
        $scope.tab = tab;
        $location.path('/'+tab);
    };
    

就这样。很难为每个页面使用单独的指令,但是在指令中使用动态templateUrl(作为函数)会导致页面的重新渲染(并丢失输入数据)。


0

如果我理解您的问题是对的,您想

  1. 当用户使用/ dashboard /:dashboardId时,最大化窗口小部件,而他最大化窗口小部件。
  2. 您希望用户能够返回/ dashboard /:dashboardId /:maximizedWidgetId并仍然看到最大化的小部件。

您只能在routerConfig中配置第一条路由,并使用RouteParams来确定是否在此已配置路由的控制器中的参数中传递了最大化的窗口小部件,并最大化了作为参数传递的一个。如果用户是第一次将其最大化,请与UI上的maximumedWidgetId共享此最大化视图的URL。

只要您使用$ location(只是本地位置对象的包装器)来更新路径,它就会刷新视图。


1
不仅$ location将刷新视图。即使不更改$ location,ng-include也将包含在内。
OZ_

@OZ_我不建议ngInclude,因为这只是视图内部的状态变化,我只是建议可能是ng-if之类的东西,它将与可以确定routeParams的函数相关联
Sivakumar Kailasam

0

我有个主意

window.history.replaceState('Object','Title','/ new-url');

如果执行此操作,然后发生摘要循环,它将完全破坏整个过程。但是,如果将其重新设置为angular认为可以的正确网址。因此,从理论上讲,您可以存储角度期望的正确网址,并在知道摘要触发之前将其重置。

我还没有测试过。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.