0

我有一个使用 ui-router 的 angularJS 组件,它有 2 个简单的路由状态。

export default function Routes($stateProvider, $urlRouterProvider, $locationProvider) {
    $stateProvider
        .state('details', {
          url: '/',
          template: '<div>...</div>'
        })
        .state('pdf', {
          url: '/viewpdf',
          template: '<pdf-viewer></pdf-viewer>'
        });

    $urlRouterProvider.otherwise(function ($injector, $location) {
        var $state = $injector.get("$state");
        $state.go("details");
    });
}

details视图中,我有一个控制器,它获取 PDF 文档,然后使用更改回调中的路由状态$state.go('pdf');

在 pdf 视图中,我有一个ui-sref链接可以返回到详细视图:

<a ui-sref="details">Back to Details</a>

间歇性地,当我按下Back to Details按钮时,它会从 page.js 引发错误并且不会更改路由状态。

Uncaught TypeError: Cannot read property '0' of undefined
    at new Context (page.js:208)
    at Function.page.replace (page.js:154)
    at onpopstate (page.js:347)
    at B (history.min.js:21)
    at history.min.js:22
Context @ page.js:208
page.replace @ page.js:154
onpopstate @ page.js:347
B @ history.min.js:21
(anonymous) @ history.min.js:22

查找我得到的错误源:(page.js:208)

/**
   * Initialize a new "request" `Context`
   * with the given `path` and optional initial `state`.
   *
   * @param {String} path
   * @param {Object} state
   * @api public
   */

function Context(path, state) {
    /* ERROR STACK ENDS ON THIS LINE */
    if ('/' == path[0] && 0 != path.indexOf(base)) path = base + path;
    /* END */
    var i = path.indexOf('?');

    this.canonicalPath = path;
    this.path = path.replace(base, '') || '/';

    this.title = document.title;
    this.state = state || {};
    this.state.path = path;
    this.querystring = ~i ? path.slice(i + 1) : '';
    this.pathname = ~i ? path.slice(0, i) : path;
    this.params = [];

    // fragment
    this.hash = '';
    if (!~this.path.indexOf('#')) return;
    var parts = this.path.split('#');
    this.path = parts[0];
    this.hash = parts[1] || '';
    this.querystring = this.querystring.split('#')[0];
  }

url 和视图停留在/viewpdf. 如果我等待几秒钟并再次按下后退按钮,它将正常工作。

是什么导致了这种行为,我该如何解决?

编辑 我应该澄清一下,当我提到后退按钮时,我指的Back to Details是视图中的按钮/viewpdf,而不是浏览器的后退按钮。浏览器后退按钮不会出现该错误。

4

1 回答 1

0

这可能会使其工作:

$state.go('state',{},{
    reload: true
});

reload文件:

https://ui-router.github.io/ng1/docs/latest/interfaces/transition.transitionoptions.html#reload

您可能还需要添加一个.then()以检查您的pdf状态在更改回details状态时是否仍在加载:

$state.go(..
    .then(
        onfulfilled,
        onrejected
    );

then()文件:

https://ui-router.github.io/ng1/docs/latest/interfaces/state.transitionpromise.html#then

更新:

如果其他导航按钮被放置在状态的组件中,则文档的这一部分可能是有用的。

https://github.com/angular-ui/ui-router/wiki#user-content-view-load-events

$rootScope.$on('$viewContentLoaded',
  function(event, viewConfig){
      // Access to all the view config properties.
      // and one special property 'targetView'
      // viewConfig.targetView
  });

在此侦听器中,您可以$scope.loaded = true 使用ng-disabled导航按钮执行类似操作。

此测试代码为导航控件配置指令,并在加载视图的 DOM 之前禁用它:

angular.module('app',['ui.router'])
  .component('componentHome', {
    template: '<div>Home Page Contents...</div>',
    controller: ['$scope','$state','$rootScope',function($scope,$state,$rootScope){
      $scope.loaded = false;
      $rootScope.$on('$viewContentLoaded',
      function(event, viewConfig){
          $scope.loaded = true;
      });
    }]
  })
  .component('componentA', {
    template: '<div><go></go></div>',
    controller: ['$scope','$state','$rootScope',function($scope,$state,$rootScope){
      $scope.loaded = false;
      $rootScope.$on('$viewContentLoaded',
      function(event, viewConfig){
          $scope.loaded = true;
      });
      $scope.stateName = 'b';
      $scope.stateLabel = 'B';
    }]
  })
  .component('componentB', {
    template: '<div><go></go></div>',
    controller: ['$scope','$state','$rootScope',function($scope,$state,$rootScope){
      $scope.loaded = false;
      $rootScope.$on('$viewContentLoaded',
      function(event, viewConfig){
          $scope.loaded = true;
      });
      $scope.stateName = 'a';
      $scope.stateLabel = 'A';
    }]
  })
  .directive('go',['$state',function($state){
    return {
      restrict: 'E',
      template: '<button ng-disabled="!loaded" state="stateName">Go to Page {{ stateLabel }}</button>',
      link: function(scope,element){
        element.on('click',function(e){
          $state.go(scope.stateName,{},{
            reload: true
          }).then(
            function(){
              // fulfilled
            },
            function(){
              // rejected
            }
          );
        });
      }
    };
  }])
  .config(function($stateProvider){
    $stateProvider.state('/',{ url: '/', component: 'componentHome' });
    $stateProvider.state('a',{ url: '/a', component: 'componentA' });
    $stateProvider.state('b',{ url: '/b', component: 'componentB' });
  })
;

使用 html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <script src="jquery.js"></script>
    <script src="angular.js"></script>
    <script src="angular-ui-router.min.js"></script>
    <style>
      .active{ border: 1px dashed red; }
    </style>
  </head>
  <body ng-app="app">
      <a ui-sref="/"  ui-sref-active="active">Home Page</a>
      <a ui-sref="a" ui-sref-active="active">Page A</a>
      <a ui-sref="b" ui-sref-active="active">Page B</a>
      <div>
        <ui-view></ui-view>
      </div>
    <script src="app.js"></script>
  </body>
</html>
于 2018-08-10T22:41:06.720 回答