【问题标题】:angularjs - refresh when clicked on link with actual urlangularjs - 单击带有实际网址的链接时刷新
【发布时间】:2012-07-01 07:25:56
【问题描述】:

我使用 routeProvider 为我的 url 定义控制器和模板。

当我单击与实际位置具有相同 url 的链接时,什么也没有发生。如果用户单击此类链接,即使位置没有更改,我也希望调用 reload() 方法。换句话说,如果我将位置设置为相同的值,我希望它的行为与将其设置为不同的值一样。

有没有办法配置 routeProvider 或 locationProvider 来自动完成?或者这样做的正确方法是什么?这是往返应用程序中的标准行为,但如何在 angularjs 中做到这一点?

我也在google groups 上问过。

更新:

这个问题得到了很多关注,所以我将尝试解释我是如何解决我的问题的。

我创建了一个自定义指令,用于在我的应用程序中进行链接,正如 Renan Tomal Fernandes 在 cmets 中所建议的那样。

angular.module('core.directives').directive('diHref', ['$location', '$route',
        function($location, $route) {
    return function(scope, element, attrs) {
        scope.$watch('diHref', function() {
            if(attrs.diHref) {
                element.attr('href', attrs.diHref);
                element.bind('click', function(event) {
                    scope.$apply(function(){
                        if($location.path() == attrs.diHref) $route.reload();
                    });
                });
            }
        });
    }
}]);

然后,该指令将用于我想要拥有此功能的应用程序中的所有链接。

<a di-href="/home/">Home</a>

该指令的作用是它根据di-href 属性为您设置href 属性,因此angular 可以像往常一样处理它,并且当您将鼠标悬停在链接上时您可以看到url。此外,当用户点击它并且链接的路径与当前路径相同时,它会重新加载路由。

【问题讨论】:

  • @public0821 的答案比选择的答案好很多
  • 请注意上面发布的代码示例,因为它会导致内存泄漏。 $watch() 包含这条指令 element.bind('click', function(event) { ... });,这意味着它将为 watcher 的每次运行创建一个单击事件处理程序,而无需释放先前的单击处理程序。

标签: javascript angularjs


【解决方案1】:

您应该使用$route.reload() 强制重新加载。

我不知道是否有“自动”的方式来做到这一点,但你可以使用 ng-click 这些链接

【讨论】:

  • 这不是很通用的解决方案。如果我想在我的整个应用程序中使用这种行为,我必须将 ng-click 添加到每个链接。
  • 也许您可以为“a”标签创建一个指令,以验证 dest url 是否与链接相同并重新加载 $route ...这是一个非常通用且很好的方法,我认为
【解决方案2】:

您可以在链接上添加_target='_self' 以强制页面重新加载。

例如

<a href="/Customer/Edit/{{customer.id}}" target="_self">{{customer.Name}}</a>

在 IE 和 Firefox 上使用 1.0.5 和 1.2.15 版本进行测试。

更多信息来自AngularJS site

HTML链接重写

当你使用HTML5历史API模式时,在不同的浏览器中你会需要不同的链接,但你所要做的就是指定常规的URL链接,例如:

<a href="/some?foo=bar">link</a>

当用户点击此链接时,

  • 在旧版浏览器中,URL 更改为 /index.html#!/some?foo=bar
  • 在现代浏览器中,URL 更改为 /some?foo=bar

在以下情况下,链接不会被重写;取而代之的是,浏览器将对原始链接执行完整的页面重新加载。

  • 包含目标元素的链接 示例:&lt;a href="/ext/link?a=b" target="_self"&gt;link&lt;/a&gt;

  • 指向不同域的绝对链接 示例:&lt;a href="http://angularjs.org/"&gt;link&lt;/a&gt;

  • 以“/”开头的链接在定义 base 时会导致不同的基本路径 示例:&lt;a href="/not-my-base/link"&gt;link&lt;/a&gt;

【讨论】:

  • 这将重新加载整个页面,最好只调用 reload() 方法,例如在指令中。
  • 但我不希望整个页面重新加载,只是角度路由机制。如果您重新加载整个页面,则它与应用程序的其余部分不一致。这就是我心中的“更好”。
  • 这实际上是一个相当不错的技巧,当您希望页面在某些链接上重新加载时...
  • target="_self" 对我来说是完美的解决方案。如果某些 GET 变量未通过,我的应用程序中有一个登录页面。此登录页面允许您设置它们,然后使用这些 GET 变量加载当前页面。我有基于这些 GET 变量的某些服务器逻辑,并且不想在 Angular 中复制逻辑。
【解决方案3】:

在路由配置中定义的 url 添加 /(斜杠)

我今天遇到了类似的问题,我的网页中有一个链接,当我点击它时,我希望每次都重新加载 ng-view,以便我可以从服务器刷新数据。但是如果 url 位置没有改变,angular 不会重新加载 ng-view。

最后,我找到了解决这个问题的方法。在我的网页中,我将链接 href 设置为:

  • &lt;a href="#/test"&gt;test&lt;/a&gt;

但是在路由配置中,我设置了:

  • $routeProvider.when('/test/', { controller: MyController, templateUrl:'/static/test.html' });

不同的是url中的最后一个斜杠。当我第一次单击href="#/test" 时,将url 重定向到#/test/,并加载ng-view。当我第二次点击它时,因为当前的url是#/test/,它不等于我点击的链接中的url(href="#/test"),所以Angular触发了位置更改方法并重新加载了ng-view,另外Angular再次将 url 重定向到 #/test/。下次我点击 url 时,angular 会再次做同样的事情。这正是我想要的。

希望这对你有用。

【讨论】:

  • 成功了!对于根,我使用了 href='#' 和 $routeProvider.when('/', ...)
  • 请注意,这也可以反过来工作,如果您不想在您的路线上使用斜杠,您可以更新您的 href 链接以使用斜杠。
  • 你成就了我的一天!优雅而简单。
  • 这是一个很好的修复,但它似乎与 html5mode(true).. 的工作方式不同。有人对 html5mode 有类似的 hack 吗?
【解决方案4】:

来自@Renan Tomal Fernandes answer。下面是一个例子

HTML

<a href="#/something" my-refresh></a>

JS

angular.module("myModule",[]).
directive('myRefresh',function($location,$route){
    return function(scope, element, attrs) {
        element.bind('click',function(){
            if(element[0] && element[0].href && element[0].href === $location.absUrl()){
                $route.reload();
            }
        });
    }   
});

【讨论】:

  • 不确定,但将此指令命名为“href”将强制所有链接正常运行,而无需更改任何标记。
  • @Lisio - 刚刚测试了您的建议,效果很好。很好的解决方案。
  • 发现如果您使用 ui-router 而不是默认路由模块,这将不起作用
  • 如果你使用的是ui-router,你可以用$state.transitionTo($state.current, $stateParams, { reload: true, inherit: false, notify: true }); 替换$route.reload
【解决方案5】:

在我的情况下,如果 url 相同,则没有任何效果,包括 $route.reload()、$location.path()、$state.transitonTo() 等。

所以我的方法是使用虚拟页面如下,

if( oldLocation === newLocation ) {
   // nothing worked ------------
   // window.location.reload(); it refresh the whole page
   // $route.reload();
   // $state.go($state.$current, null, { reload: true });
   // $state.transitionTo($state.current, $stateParams, {reload:true, inherit: false, notify: false } );
   // except this one
   $location.path('/dummy'); 
   $location.path($location.path());
   $scope.$apply(); 
}

你需要在某处制作'/dummy'模块,该模块不做任何事情,它只是改变url,以便下一个$location.path()可以 应用。不要错过 $scope.$apply()

【讨论】:

    【解决方案6】:

    刚刚尝试添加这个

    $(window).on('popstate', function(event) {
    //refresh server data
    });
    

    效果很好

    【讨论】:

      【解决方案7】:

      我刚才遇到了这个问题,除了它是主页'/'。我想要一个代码更少的简单解决方案。我只是利用了 $routProvider 中的 .otherwise 方法

      所以在 html 中的链接看起来像:

      <a href="#/home">Home</a>
      

      由于 routProvider 中没有指定 '/home' 页面,它将通过 'otherwise' 方法重定向到 '/'。具有此设置的页面:

      .otherwise({
      redirectTo: '/'
      });
      

      希望对某人有所帮助

      【讨论】:

        【解决方案8】:

        对于使用AngularUI Router 的人。你可以使用这样的东西:

        <a data-ui-sref="some.state" data-ui-sref-opts="{reload: true}">State</a>
        

        注意重新加载选项。

        在这里找到答案:https://stackoverflow.com/a/29384813/426840

        【讨论】:

        • 上面的“解决方案”都没有对我有用,但是这个对我有用!
        【解决方案9】:

        我使用指令方法尝试了上述 Wittaya 的解决方案。不知何故,指令不断抛出错误。我最终得到了这个解决方案

        HTML

        <a href="javascript:void(0)" data-ng-click="stateGo('devices')">Devices</a>
        

        控制器

            $scope.stateGo = function (stateName) {
                if ($state.$current.name === stateName) {
                    $state.reload();
                } else {
                    $state.go(stateName);
                }
            }
        

        【讨论】:

          【解决方案10】:

          我认为这是一种更简单的方法。

          .directive ('a', function ($route, $location) {
              var d = {};
              d.restrict = 'E';
              d.link = function (scope, elem, attrs) {
          
                  // has target
                  if ('target' in attrs) return;
          
                  // doesn't have href
                  if (!('href' in attrs)) return;
          
                  // href is not the current path
                  var href = elem [0].href;
                  elem.bind ('click', function () {
                      if (href !== $location.absUrl ()) return;
                      $route.reload ();
                  });
              };
              return d;
          });
          

          假设您想让所有基本的&lt;a&gt; 链接(没有target 属性)在单击时重新加载,并且您在href 属性中使用相对链接(例如/home 而不是http://example.com/home)您不必须向您的 HTML 添加任何特殊标记(在使用已编写的 HTML 更新站点时会派上用场)。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-05-09
            • 2017-07-08
            • 2014-01-14
            • 2015-12-22
            • 1970-01-01
            • 2016-10-02
            • 1970-01-01
            • 2014-11-21
            相关资源
            最近更新 更多