ionic1中Tab与新页面URL命名相似导致的路由冲突

版权声明:原创不易,转载须经作者同意 https://blog.csdn.net/zhichaosong/article/details/88744900

摘要:运行 ionic1 的官方 tab 示例 Demo,新添加一个子页面一切正常,但是当把新页面的 URL 改成与任一 tab 名字相似却不显示页面了。反复尝试发现是 $ionicTab 源码的原因,详细解析如下。

一、冲突复现

1. 新建项目

ionic start myApp tabs
ionic serve

2. 新增页面

① templates 文件夹下创建 new.html

<ion-view view-title="Dashboard">
    <ion-content class="padding">
        <h2>New Page</h2>
    </ion-content>
</ion-view>

② app.js 下增加 state

            .state('tab.new', {
                url: '/new',
                views: {
                    'tab-dash': {
                        templateUrl: 'templates/new.html',
                        controller: 'NewCtrl'
                    }
                }
            })

③ 修改 controller.js

.controller('DashCtrl', function($scope, $state) {
    $scope.go = function() {
        $state.go('tab.new');
    }
})
.controller('NewCtrl', function($scope, $stateParams, Chats) {
})

④ 修改 tab-dash.html

<button class="button button-full" ng-click="go()">state:tab.new</button>

⑤ 运行项目,进入新页面,一切正常
正常页面

3. 故障复现

① 修改 app.js 中新页面的路径

            .state('tab.new', {
                url: '/chats1', //只改了这一行
                views: {
                    'tab-dash': {
                        templateUrl: 'templates/new.html',
                        controller: 'NewCtrl'
                    }
                }
            })

② 运行项目,进入新页面,页面空白,且 tab 标记为 Chats 标签
异常页面

二、原因分析

1. 浏览器 Debug

浏览器中查看页面元素,发现多了一个空的 <ion-nav-view name="tab-chats">,大致猜测是 URL 解析错误导致 Chats 所属的 tab 误加载了
页面调试

2. 对比两次页面

对比页面发现也只多了这一部分,其他的代码没有区别
两次页面对比

3. 修改 tabs.html 测试

将 href 从 #/tab/chats改为 #/tab/ccc,发现页面可以正常显示了,由此锁定为 <ion-tab> 的解析问题,下面查看源码分析原因

  <!-- Chats Tab -->
  <ion-tab title="Chats" icon-off="ion-ios-chatboxes-outline" icon-on="ion-ios-chatboxes" href="#/tab/ccc">
    <ion-nav-view name="tab-chats"></ion-nav-view>
  </ion-tab>

三、源码解析

查看 ionic.bundle.js 的 61639 行 $ionicTab指令的定义,发现 hrefMatchesState ()方法进行了 URL 匹配,此函数将 当前 URL 与 tab 所属的 URL 进行 indexOf 比对查找,chats1 与 chats 成功进行了匹配,所以导致 tab 选择错误。

IonicModule
.controller('$ionicTab', [
  '$scope',
  '$ionicHistory',
  '$attrs',
  '$location',
  '$state',
function($scope, $ionicHistory, $attrs, $location, $state) {
  this.$scope = $scope;

  //All of these exposed for testing
  this.hrefMatchesState = function() {
    return $attrs.href && $location.path().indexOf(
      $attrs.href.replace(/^#/, '').replace(/\/$/, '')
    ) === 0;
  };
  this.srefMatchesState = function() {
    return $attrs.uiSref && $state.includes($attrs.uiSref.split('(')[0]);
  };
  this.navNameMatchesState = function() {
    return this.navViewName && $ionicHistory.isCurrentStateNavView(this.navViewName);
  };

  this.tabMatchesState = function() {
    return this.hrefMatchesState() || this.srefMatchesState() || this.navNameMatchesState();
  };
}]);

四、解决措施

从正则表达式看出,函数去掉了 tab 中 URL 前面的 #和后面的 /,这样导致误匹配的概率大大增加,因此我们保留后面的斜杠,并且在 tabs.html 中的 href 后面全部增加 /即可解决错误匹配导致的冲突问题,代码如下所示:
① 修改 tabs.html

<ion-tabs class="tabs-icon-top tabs-color-active-positive">

  <!-- Dashboard Tab -->
  <ion-tab title="Status" icon-off="ion-ios-pulse" icon-on="ion-ios-pulse-strong" href="#/tab/dash/">
    <ion-nav-view name="tab-dash"></ion-nav-view>
  </ion-tab>

  <!-- Chats Tab -->
  <ion-tab title="Chats" icon-off="ion-ios-chatboxes-outline" icon-on="ion-ios-chatboxes" href="#/tab/chats/">
    <ion-nav-view name="tab-chats"></ion-nav-view>
  </ion-tab>

  <!-- Account Tab -->
  <ion-tab title="Account" icon-off="ion-ios-gear-outline" icon-on="ion-ios-gear" href="#/tab/account/">
    <ion-nav-view name="tab-account"></ion-nav-view>
  </ion-tab>


</ion-tabs>

② 修改 ionic.bundle.js

IonicModule
.controller('$ionicTab', [
  '$scope',
  '$ionicHistory',
  '$attrs',
  '$location',
  '$state',
function($scope, $ionicHistory, $attrs, $location, $state) {
  this.$scope = $scope;

  //All of these exposed for testing
  this.hrefMatchesState = function() {
      console.log('$attrs.href : ' + $attrs.href);
      console.log('$location.path : ' + $location.path());
      console.log('replace : ' + $attrs.href.replace(/^#/, ''));
      console.log('indexOf : ' + $location.path().indexOf(
          $attrs.href.replace(/^#/, '').replace(/\/$/, '')
      ));
    // return $attrs.href && $location.path().indexOf(
    //   $attrs.href.replace(/^#/, '').replace(/\/$/, '')
    // ) === 0;
    return $attrs.href && $location.path().indexOf(
      $attrs.href.replace(/^#/, '')//此处去掉后斜杠的替换操作
    ) === 0;
  };
  this.srefMatchesState = function() {
    return $attrs.uiSref && $state.includes($attrs.uiSref.split('(')[0]);
  };
  this.navNameMatchesState = function() {
    return this.navViewName && $ionicHistory.isCurrentStateNavView(this.navViewName);
  };

  this.tabMatchesState = function() {
    return this.hrefMatchesState() || this.srefMatchesState() || this.navNameMatchesState();
  };
}]);

猜你喜欢

转载自blog.csdn.net/zhichaosong/article/details/88744900