【问题标题】:Updating URL in Angular JS without re-rendering view在 Angular JS 中更新 URL 而无需重新渲染视图
【发布时间】:2013-08-22 14:59:42
【问题描述】:

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

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

目前,我们有 2 条路线,类似于 /dashboard/:dashboardId/dashboard/:dashboardId/:maximizedWidgetId

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

HTML5Mode 设置为true

【问题讨论】:

  • 如果您希望您的数据在客户端路由更改后仍然存在,为什么不将其推送到服务中?

标签: angularjs angularjs-routing


【解决方案1】:

实际上,每次更改 url 时都会呈现一个视图。这就是 $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);

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

您甚至可以查看 URL 中的搜索更改(从一个小部件到另一个小部件)

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

【讨论】:

  • 如果它会被接受,我将创建一个单独的问题,没有任何“:param”的东西。只是简单的愚蠢问题:如何不重新渲染视图。
  • 我认为angular-ui-router 在这种情况下将是一个显而易见的选择。
  • 我正在使用$routeUpdate 事件。我认为$routeChangeStart 在移动到另一个位置时会被触发。
  • @kuchumovn:不幸的是,我们仍处于 2014 年。Angular 2.0 将有一个改进的路由(可能是内置的 angular-ui-router),它可以满足您的预期。
  • @codef0rmer,我不止一次找到了这个答案。谢谢!很好的答案,毕竟这么久了!
【解决方案2】:

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

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

问候

【讨论】:

  • 看起来是重复的。不幸的是,看起来他们有同样的问题,只要它是 url 路径的一部分,而不是查询变量,它就会刷新。
  • 不,不是重复的。
  • 这不是重复的,因为链接的问题是关于不重新加载控制器,这是关于不重新加载模板。链接问题中的解决方案将使视图重新加载。
【解决方案3】:

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

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

用法:

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

【讨论】:

  • 谢谢,工作。但也许你不应该扩展原来的 $location?
【解决方案4】:

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

【讨论】:

  • 你试过用$state.transitionTo()代替$location.path()吗?
  • 我根本不改变$location.path(),那么$state.transitionTo()应该写在哪里?
  • 引用:“当用户最大化小部件时,我们使用 location.path 更新 url,但这会导致视图重新呈现。”您应该调用 $state.transitionTo() 而不是更改路径,这反过来会更新 url 哈希。
  • 这个想法是您应该有两种嵌套状态:一种用于仪表板,另一种用于最大化小部件。当你从父状态导航到子状态时,只有子视图会重新渲染,而不是父视图。
【解决方案5】:

我知道这是一个老问题,但由于我花了一天半的时间才找到答案,所以就这样吧。

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

目前,由于may be considered as a bug 的原因,在状态上设置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
  });

就是这样。希望这会有所帮助!

【讨论】:

    【解决方案6】:

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

    我有一个带有菜单的页面(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(作为函数)会引发页面重新渲染(并丢失输入数据)。

    【讨论】:

      【解决方案7】:

      如果我理解你的问题,你愿意,

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

      您可以只配置 routerConfig 中的第一个路由,并使用RouteParams 来识别是否在此配置路由的控制器中的参数中传递了最大化的小部件,并最大化作为参数传递的那个。如果用户是第一次将其最大化,请使用 UI 上的 minimizedWidgetId 共享此最大化视图的 url。

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

      【讨论】:

      • 不仅$location 会刷新视图。 ng-include 也会,即使不改变 $location。
      • @OZ_ 我不建议使用 ngInclude,因为这只是视图内的状态更改,我只是建议可能类似于 ng-if 之类的东西,它与可以计算 routeParams 的函数相关联
      【解决方案8】:

      我有个想法要使用

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

      如果您这样做并且发生了一个摘要循环,它将完全搞砸事情。但是,如果您将其设置回正确的 url,则 angular 期望它可以。因此,理论上您可以存储 angular 期望的正确 url,并在您知道摘要触发之前将其重置。

      不过我还没有测试过。

      【讨论】:

        【解决方案9】:

        下面的代码将让您无需重定向即可更改 url,例如: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时,你会被重定向。

        【讨论】:

        • 我不明白为什么要在这里添加另一个答案。
        • 它是对历史的注解。
        猜你喜欢
        • 2023-03-22
        • 1970-01-01
        • 2017-06-25
        • 1970-01-01
        • 1970-01-01
        • 2021-11-04
        • 1970-01-01
        • 2019-09-26
        • 2015-06-30
        相关资源
        最近更新 更多