【问题标题】:Angular UI router's "resolve" fires twiceAngular UI 路由器的“resolve”触发两次
【发布时间】:2016-01-26 19:53:48
【问题描述】:

我正在使用angular ui router 在我的前端处理一些路由。这就是我的路由代码的样子。

// angular config

$stateProvider.state('app', {
    templateUrl: '/static/partials/home.html',
    controller: 'NavCtrl'
});

$stateProvider.state('app.reader', {
    url : '/reader/*path?start&end&column&page',
    templateUrl: '/static/partials/reader.html',
    resolve : {
        panelContent : [
            '$state', '$stateParams', '$http',
            function ($state, $stateParams, $http) {
                alert('resolving panel Content');
                return [];  // simplest thing possible to illustrate my point
            }
        ]
    },
    controller: 'ReaderCtrl'
});

/// etc etc

$urlRouterProvider.otherwise('/reader/');

我的 html 使用了多个嵌套视图,我会尽力说明

index.html

<html>
    <div ui-view></div>     <!-- /static/partials/home.html gets injected here -->
</html>

/static/home.html

<html>
    <!-- some side bar stuff -->

    <!-- reader -->
    <div ui-view></div>    <!-- /static/partials/reader.html gets injected here -->
</html>

所以我有多层嵌套

-- index.html
    -- home.html
        -- reader.html

现在,当我第一次加载页面时,我的警报消息

alert('resolving panel Content');

只触发一次......这是有道理的。但是,假设我在分页中单击“下一页”..

<!-- inside /static/partials/reader.html -->   

<uib
    pagination total-items= "totalItems"
    ng-model= "pageNumber"
    ng-change= "pageUpdate"
    max-size= "maxPageNumbersDisplayed"
></uib>

这最终会在我的“ReaderCtrl”中触发一个函数

$scope.pageUpdate(page) {
    $state.go( '.', {page: page}); 
}   

这会更新 url,从变成这样的东西

/#/reader/<my path>

这样的事情

/#/reader/<my_path>?page=2

现在是让我扯掉头发的部分。

我回到我的路由阅读器部分中的“解决”代码块。

警报消息出现两次。

通过在 Web 控制台中进行一些调试,我发现订单正常

 1) alert message in resolve
 2) travel through the entirety of ReaderCtrl
 3) lots and lots of angular calls
 4) alert message (2nd time)
 5) travel through entirety of ReaderCtrl a second time.

您可能倾向于知道 NavCtrl 中发生了什么,但我不会在那里拨打任何电话。 NavCtrl 中的所有内容都是 ReaderCtrl 可以继承的函数,以更新 /static/partials/home.html 的范围

真的,我好像被困在第 3 步了。

有没有人知道为什么我的 resolve 块似乎被触发了两次?

编辑:

经过更多调试,我似乎发现顺序是这样的,从“updatePage”函数执行后立即开始。

1) first "resolving message"
    -- the url has not yet changed
2) second "resolving message"
    -- the url appears to have changed very shortly before this message

所以,我想我现在的问题是...... 为什么

$state.go('.', args);

在第一个警报触发之前不更改 url,但在第二个警报处/附近更改 url?

编辑 2:最终无法解决我的问题,所以我暂时围绕它进行了破解......我基本上做了一个函数来完成我假设 $state.go() 在幕后所做的事情,并构造了 url。

function _mk_url(args) {

    var url = "/reader";

    var pageNumber = args.pageNumber || 1;
    url += "?page=" + pageNumber;

    var columns = args.columns || [];
    columns.forEach(function(d) {
        url += "&column=" + d;
    });

    //etc..

    return url;
}

var args = {"columns" : ["a", "b", "c"], "pageNumber" : 2};
var url = _mk_url(args);
$location.url(url);

【问题讨论】:

  • 从阅读中我认为问题在于ReaderCtrl 中的状态更改并且它正在重新渲染。然后它再次解析路由以获取路由参数。
  • 我添加了一些警告行,我发现 1) 第一个解析被调用 2) 然后 url 更改 3) 下一个解析触发。因此,第一个 $state.go( ... ) 似乎触发了路由/解析,而没有实际更改路径。然后当路径 ACTUALLY 改变时,再次触发解析。
  • github.com/angular-ui/ui-router/wiki#resolve 您是否尝试使用仅在之后触发的$stateChangeSuccess
  • 我尝试在 $state.go('.', args, {notify : true}) 中使用 notify 来提醒状态变化,但它没有用。使用 $stateChangeSuccess 是什么意思

标签: javascript angularjs routing angular-ui-router nested-views


【解决方案1】:

我遇到了这个问题,发现这是因为我在代码的其他地方手动调用了我的解析函数。在您的代码中搜索panelContent(),您可能会发现它再次被触发的位置。

【讨论】:

    【解决方案2】:

    我遇到了这个问题。原因在我的 html 模板中。我在子元素和父元素中都使用了ui-sref 指令

    <li ui-sref="{{r.name}}" ng-class="vm.isCurrent(r)" ng-repeat="r in vm.settingsRoutes"> <span ui-sref="{{r.name}}" ng-bind-html="r.title"></span> </li>

    所以当我点击span 时,我触发了stateChange 两次。

    【讨论】:

      【解决方案3】:

      我也遇到过同样的错误。 我发现我在其中一个解析函数中被更改了$stateParams。 解决方案是从此对象制作副本,然后使用副本执行您想要的操作。

      resolve: {
      
            /** @ngInject */
            searchParams: function ($stateParams) {
              let params = angular.copy($stateParams); // good
      
              // good: 
              if (params.pending === undefined) {
                params.pending = true;
              }
      
              // bad: 
              if ($stateParams.redirect === 'true') {
                $stateParams.pending = false; // this line changing the URL
              }
              return params;
            },
      

      }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-31
        • 1970-01-01
        • 2016-11-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多