在不重新渲染视图的情况下更新Angular JS中的URL

时间:2013-08-20 14:03:36

标签: angularjs angularjs-routing

我正在AngularJS中构建一个仪表板系统,我遇到了通过$location.path

设置网址的问题

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

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

的路线

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

HTML5Mode设置为true

9 个答案:

答案 0 :(得分:128)

实际上,每次更改网址时都会呈现视图。这是$ routeProvider如何在Angular中工作,但是您可以将maximizeWidgetId作为查询字符串传递,而不会重新渲染视图。

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

您甚至可以观看网址(从一个小部件到另一个小部件)的搜索更改

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

答案 1 :(得分:8)

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

可能重复的问题:Can you change a path without reloading the controller in AngularJS?

此致

答案 2 :(得分:6)

对于那些需要更改完整路径()而没有控制器重新加载的人

这是插件:https://github.com/anglibs/angular-location-update

用法:

$location.update_path('/notes/1');

答案 3 :(得分:3)

我们使用Angular UI Router而不是类似场景的内置路由。它似乎没有重新实例化控制器并重新渲染整个视图。

答案 4 :(得分:3)

我意识到这是一个古老的问题,但是因为我花了一大半的时间才找到答案,所以就这样了。

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

目前,由于may be considered as a bug的原因,在状态上设置reloadOnSearch: false将导致能够在不重新加载视图的情况下更改路径。 GitHub用户lmessinger甚至还提供了它的演示。您可以在上面链接的评论中找到该链接。

基本上你需要做的就是:

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

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

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

    那就是它。希望这有帮助!

答案 5 :(得分:2)

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

我有菜单页面(menuPage),导航时不应该清理数据(每页都有很多输入,如果数据意外消失,用户会非常不满意。)

  1. 关闭$ routeProvider
  2. 主页控制器中的
  3. 使用自定义指令属性添加两个div - 每个指令仅包含'templateUrl'和'scope:true'

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

    if (!$scope.tab && $location.path()) {
        $scope.tab = $location.path().substr(1);
    }
    $scope.setTab = function(tab) {
        $scope.tab = tab;
        $location.path('/'+tab);
    };
    
  5. 这就是全部。对于每个页面都有单独的指令有点难看,但在指令中使用动态templateUrl(作为函数)会引起页面的重新呈现(以及丢失输入的数据)。

答案 6 :(得分:0)

如果我理解你的问题,你想,

  1. 当用户在/ dashboard /:dashboardId上时最大化窗口小部件,并且他最大化窗口小部件。
  2. 您希望用户能够返回/ dashboard /:dashboardId /:maximizedWidgetId并仍然可以看到窗口小部件最大化。
  3. 您只能在routerConfig中配置第一个路由,并使用RouteParams来识别最大化的窗口小部件是否在此配置路由的控制器中的params中传递,并最大化作为参数传递的窗口小部件。如果用户第一次将其最大化,请使用UI上的maximizedWidgetId将该URL分享到此最大化视图。

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

答案 7 :(得分:0)

我有想法使用

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

如果你这样做并且发生了一个摘要循环,那么它将完全破坏。但是,如果您将其设置回角度预期正常的正确URL。所以从理论上讲,你可以存储角度所需的正确url,并在知道摘要消息之前重置它。

我没有测试过这个。

答案 8 :(得分:-2)

下面的代码可让您更改网址而无需重定向,例如:http://localhost/#/691?foo?bar?blabla

for(var i=0;i<=1000;i++) $routeProvider.when('/'+i, {templateUrl: "tabPages/"+i+".html",reloadOnSearch: false});

但是当您更改为http://localhost/#/692时,您将被重定向。