遍历多视图状态树时,UI路由器转换被取代

时间:2017-11-30 17:21:42

标签: angularjs angular-ui-router

我试图通过多视图管理我的管理页面:admin,admin.header,admin.leftPanel,admin.main,admin.tail。在header,leftPanel,main和tail中,我分别使用$ state.go来显示它们的子状态以呈现它们的内容。我写了一些简单的代码来演示这个问题。

演示陈述模型:

state1:
  state2view
    controller: $state.go(state1.state2) <---superseded
  state3view
    controller: $state.go(state1.state3)

代码(plunker):

&#13;
&#13;
<!DOCTYPE html>
<html ng-app="demo">

  <head>
    <meta charset="utf-8" />
    <title>Demo</title>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.6/angular.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/1.0.3/angular-ui-router.js"></script>
    <script>
      let app = angular.module('demo', ['ui.router']);
    
      app.config(['$urlRouterProvider', '$stateProvider', function ($up, $sp) {
        $sp.state('state1', state1);
        $sp.state('state1.state2', new SubState('state2view'));
        $sp.state('state1.state3', new SubState('state3view'));
        $up.otherwise('/');
      }]);
      
      let state1 = {
        url: '/',
        views: {
          "state1view1": {
            controller: ['$transition$', '$state', function ($tr, $st) {
              this.stateName = $st.current.name;
              $st.go('state1.state2', {message: 'message from ' + $st.current.name + ' to ' + $st.current.name + '.state2'});
            }],
            controllerAs: '$ctrl',
            template: `<div>
              {{$ctrl.stateName}} begin<br>
              <ui-view name="state2view"></ui-view>
              {{$ctrl.stateName}} end
            </div>`
          },
          
          "state1view2": {
            controller: ['$transition$', '$state', function ($tr, $st) {
              this.stateName = $st.current.name;
              $st.go('state1.state3', {message: 'message from ' + $st.current.name + ' to ' + $st.current.name + '.state3'});
            }],
            controllerAs: '$ctrl',
            template: `<div>
              {{$ctrl.stateName}} begin<br>
              <ui-view name="state3view"></ui-view>
              {{$ctrl.stateName}} end
            </div>`
          }
        }
      };
      
      function SubState(view1Name) {
        this.params = {message: ''};
        this.views = {};
        this.views[view1Name] = {
          controller: ['$transition$', '$state', function ($tr, $st) {
            this.parentMessage = $tr.params().message;
            this.stateName = $st.current.name;
          }],
          controllerAs: '$ctrl',
          template: `<div>
            {{$ctrl.stateName}} begin<br>
            {{$ctrl.parentMessage}}<br>
            {{$ctrl.stateName}} end
          </div>`
        };
      }
      
      app.run(function($transitions) {
        $transitions.onStart({}, function($tr) {
            console.log("trans begin: " + $tr.from().name + " -> " + $tr.to().name);
          }
        );
        $transitions.onSuccess({}, function($tr) {
            console.log("trans done: " + $tr.from().name + " -> " + $tr.to().name);
          }
        );
      });

    </script>
    <style>
    div{border-style: solid;}
    </style>
  </head>

  <body>
    <ui-view name="state1view1"></ui-view>
    <br>
    <ui-view name="state1view2"></ui-view>
  </body>

</html>
&#13;
&#13;
&#13;

预期结果:

state1 begin
state1.state2 begin
message from state1 to state1.state2
state1.state2 end
state1.state3 begin
message from state1 to state1.state3
state1.state3 end
state1 end

实际结果:

state1 begin
state1 end
state1 begin
state1.state3 begin
message from state1 to state1.state3
state1.state3 end
state1 end

控制台输出: console output

2 个答案:

答案 0 :(得分:0)

您应该使用@ marklagendijk创建的stateHelper模块。

如果您不想使用上述模块,请阅读以下链接中有关嵌套状态的文章以获取更多选项

Nested States

plunkr

angular.module('app').config([
'$urlRouterProvider',
 'stateHelperProvider',
 function($urlRouterProvider, stateHelperProvider) {
stateHelperProvider.state({
  name: 'state1',
  template: '<ui-view/>',
  abstract: true,
  resolve: {
    // haven't got to this point yet :-/
  },
  children: [{
      name: 'state2',
      controller:['$state','$q', function ( $st,$q) {
          this.stateName = $st.current.name;
         // $st.transitionTo('state1.state2', {message: 'message from ' + $st.current.name + ' to ' + $st.current.name + '.state2'});
        }], controllerAs: '$ctrl',
      url : '/',
      template: `<br>{{$ctrl.stateName}} begin
      <br>message from {{$ctrl.stateName}} to {{$ctrl.stateName}}.state3
      <br>{{$ctrl.stateName}} end`
  },{
      name: 'state3',
      url : '/',
      controller:['$state','$q', function ( $st,$q) {
          this.stateName = $st.current.name;

         // $st.transitionTo('state1.state2', {message: 'message from ' + $st.current.name + ' to ' + $st.current.name + '.state2'});
        }], controllerAs: '$ctrl',
      template: `<br>{{$ctrl.stateName}} begin
      <br>message from {{$ctrl.stateName}} to {{$ctrl.stateName}}.state3
      <br>{{$ctrl.stateName}} end`
  }]
});}]);

答案 1 :(得分:0)

事实证明我只是碰壁了。

通过逐个访问这些状态将将页面内容封装到UI路由器状态和布局中的想法是完全错误的。特别是,您无法显示两个兄弟一次陈述观点。

UI路由器专为通过鼠标点击进行路由而设计。即使拼接文档强烈提示我们可以在状态树上中继我们的整页以布局所有内容,但情况并非总是如此。只要app逻辑转移到另一个不是from-state的后果的状态,from-state就会在进入to-state之前退出,并且它的运行时生成的退出状态视图被完全删除

Bellow代码最初试图证明我的概念(原始问题中的设计改进,因为我意识到状态中没有断点/简历设计)并解决了我的问题,但事实证明作为揭示相反的例子 - 在错误的想法下不可能。

概念

  1. 定义状态及其层次结构和模板以构建页面布局;
  2. 制作州树;
  3. 制作遍历路径;
  4. 通过$ state.go遍历路径到每个州展开并呈现布局。
  5. 代码plnkr

            if (cursor.moveToFirst()) {
                List<DataPoint> dataPoints = new ArrayList<DataPoint>();
                do {
                    dataPoints.add(
                        new DataPoint(cursor.getInt(0),
                                  cursor.getInt(1)));
    
                } while (cursor.moveToNext());
    
                LineGraphSeries<DataPoint> series = new LineGraphSeries<>(
                    dataPoints.toArray(new DataPoint[0]));
            }
    

    结果(Firefox 57.0.1)

    进入页面时: enter image description here

    点击并关闭提醒后: enter image description here

    上面的过程显示state1.state2已执行并已布局(但尚未按角度进行评估/渲染),正如我们在第一张图片中所见。此时退出尚未发生,因为onExit警报弹出窗口阻止了该进程。警报弹出窗口关闭后,状态退出,视图完全删除。

    为页面内标签特定目的开发了sticky-state,但是我尝试过它在这里不起作用。它记得最后访问过的棒状态,但是已经删除了退出状态的视图。

    我现在正尝试将UI路由器用作路由表示法工具。但我必须非常清醒,不要忘记 UI路由器可以用作布局页面的通用工具,如角度组件的扩展。但这可能很难:我想不出目前使用UI路由器的正确模式。在多视图的情况下,如果任何两个兄弟视图都有自己的子状态,我必须非常小心,因为访问一个退出另一个 - 它们是独占的。这让我觉得不值得复杂。

    虽然在大多数情况下在导航过程中需要删除退出视图,但我建议UI路由器进行更改并提供保留视图以提供更多灵活性的机会。它可能比第一个想法更复杂,但它应该是可能的。

    还希望为每个状态缓存所有“最后看到的”参数(不仅仅是粘滞状态),这样我们就可以轻松地返回它们。您可能会争论用例,但我们无法想象人们将如何使用工具而不应限制其可能性。

    还希望为每个州的基地提供全生命周期挂钩设施(现在只有onEnter和onExit)。