使用ng-if

时间:2015-06-15 07:56:51

标签: javascript css angularjs ionic-framework

我正在为应用做一个介绍屏幕。此屏幕(3张幻灯片)仅在新用户上显示。所以我这样做的方式是:

  1. 默认路线始终转到此介绍屏幕

  2. 从介绍屏幕控制器中,检查(cookie)以查看用户之前是否已看过此屏幕。依赖于此,切换$scope.showIntro。然后$state.go()到下一个主应用屏幕。

  3. 在介绍视图中,使用ng-if="showIntro"。因此,如果$ scope.showIntro == false,则DOM为空。

  4. 以下是棘手的部分:

    1. 无法检查用户是否看过此屏幕,因为我使用的是$localStorage,当我创建路线时,它并不存在于app()中。这就是我必须在控制器中执行此检查逻辑的原因。

    2. 我必须使用ng-if,因为如果我使用ng-show,它的速度太慢,用户会在路由到主屏幕之前看到一些介绍屏幕。< / p>

    3. 问题:

      如果我在ng-if组件上使用ion-view,则一旦将DOM再次注入视图,标题就不会刷新为什么这样以及如何解决这个问题?也许某种方式重新运行摘要?

      代码 http://codepen.io/hawkphil/pen/jPLqge

      &#13;
      &#13;
      angular.module('ionicApp', ['ionic'])
          
      .config(function($stateProvider, $urlRouterProvider) {
          
      $stateProvider
            .state('intro', {
              url: '/',
              templateUrl: 'templates/intro.html',
              controller: 'IntroCtrl'
            })
            .state('main', {
              url: '/main',
              templateUrl: 'templates/main.html',
              controller: 'MainCtrl'
            });
          
            $urlRouterProvider.otherwise("/");
          
          })
          
          .controller('IntroCtrl', function($scope, $state, $ionicSlideBoxDelegate) {
            $scope.title = "<b>CUSTOM</b> TITLE";
            $scope.showIntro = true;
            
            // Called to navigate to the main app
            $scope.startApp = function() {
              $state.go('main');
            };
            $scope.next = function() {
              $ionicSlideBoxDelegate.next();
            };
            $scope.previous = function() {
              $ionicSlideBoxDelegate.previous();
            };
          
            // Called each time the slide changes
            $scope.slideChanged = function(index) {
              $scope.slideIndex = index;
            };
          })
          
          .controller('MainCtrl', function($scope, $state) {
            console.log('MainCtrl');
            
            $scope.toIntro = function(){
              $state.go('intro');
            }
          });
      &#13;
          body {
            cursor: url('http://ionicframework.com/img/finger.png'), auto;
          }
          .slider {
            height: 100%;
          }
          .slider-slide {
            padding-top: 80px;
            color: #000;
            background-color: #fff;
            text-align: center;
          
            font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; 
            font-weight: 300;
          }
          
          #logo {
            margin: 30px 0px;
          }
          
          #list {
            width: 170px;
            margin: 30px auto;
            font-size: 20px;
          }
          #list ol {
            margin-top: 30px;
          }
          #list ol li {
            text-align: left;
            list-style: decimal;
            margin: 10px 0px;
          }
          
          .button.ng-hide{
            display:none;
          }
      &#13;
          <html>
            <head>
              <meta charset="utf-8">
              <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
              <title>Ionic App</title>
          
              <link href="//code.ionicframework.com/nightly/css/ionic.css" rel="stylesheet">
              <script src="//code.ionicframework.com/nightly/js/ionic.bundle.js"></script>
            </head>
          
            <body ng-app="ionicApp">
          
              <ion-nav-bar class="bar-light">
                  <ion-nav-back-button>
                  </ion-nav-back-button>
              </ion-nav-bar>
          
              <ion-nav-view></ion-nav-view>
          
          
              <script id="templates/intro.html" type="text/ng-template"> 
                <ion-view view-title="{{ title }}" ng-if="showIntro">
                  <ion-nav-buttons side="left">
                    <button class="button button-positive button-clear no-animation"
                            ng-click="startApp()" ng-show="!slideIndex">
                      Skip Intro
                    </button>
                    <button class="button button-positive button-clear no-animation"
                            ng-click="previous()" ng-show="slideIndex > 0">
                      Previous Slide
                    </button>
                  </ion-nav-buttons>
                  <ion-nav-buttons side="right"> 
                    <button class="button button-positive button-clear no-animation"
                            ng-click="next()" ng-show="slideIndex != 2">
                      Next
                    </button>
                    <button class="button button-positive button-clear no-animation"
                            ng-click="startApp()" ng-show="slideIndex == 2">
                      Start using MyApp
                    </button>
                  </ion-nav-buttons>
                  <ion-slide-box on-slide-changed="slideChanged(index)">
                    <ion-slide>
                      <h3>Thank you for choosing the Awesome App!</h3>
                      <div id="logo">
                        <img src="http://code.ionicframework.com/assets/img/app_icon.png">
                      </div>
                      <p>
                        We've worked super hard to make you happy.
                      </p>
                      <p>
                        But if you are angry, too bad.
                      </p>
                    </ion-slide>
                    <ion-slide>
                      <h3>Using Awesome</h3>
                      
                      <div id="list">
                        <h5>Just three steps:</h5>
                        <ol>
                          <li>Be awesome</li>
                          <li>Stay awesome</li>
                          <li>There is no step 3</li>
                        </ol>
                      </div>
                    </ion-slide>
                    <ion-slide>
                      <h3>Any questions?</h3>
                      <p>
                        Too bad!
                      </p>
                    </ion-slide>
                  </ion-slide-box>
                </ion-view>
              </script>
          
              <script id="templates/main.html" type="text/ng-template">
                <ion-view hide-back-button="true" view-title="Awesome">
                  <ion-content class="padding">
                    <h1>Main app here</h1>
                    <button class="button" ng-click="toIntro()">Do Tutorial Again</button>
                  </ion-content>
                </ion-view>
              </script>
              
            </body>
          </html>
      &#13;
      &#13;
      &#13;

      编辑1

      http://plnkr.co/edit/1FYr6GK6xMQjp9hA3N0M?p=preview

      以下答案的示例仅在介绍状态为/作为网址路由时才有效。但是如果你放置/intro或其他网址,状态就会继续进行迭代(截图)。

      function config($stateProvider, $urlRouterProvider) {
        $stateProvider
      
          .state('intro', {
            url: '/intro',
            templateUrl: 'intro.html',
            controller: 'IntroCtrl',
            data: {
              isIntro: true
            },          
          })
      
          .state('main', {
            url: '/main',
            templateUrl: 'main.html',
            controller: 'MainCtrl',
            data: {
              isIntro: false
            },            
          });
      
          $urlRouterProvider.otherwise("/intro");
      }
      

      enter image description here

1 个答案:

答案 0 :(得分:1)

您可以在视图开始之前使用$stateChangeStart检查本地存储:

$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
    console.log("$rootScope => $stateChangeStart => " + toState.name || '');

    if (toState.data && angular.isObject(toState.data)) {
    if (toState.data.isIntro && $localStorage.visitedIntro)
    {
        event.preventDefault();
        $state.go("main");
    } 
    }
});  

我所做的是将属性附加到每个州,因此我确切地知道哪个是前奏( data.isIntro ):

.state('intro', {
  url: '/',
  templateUrl: 'intro.html',
  controller: 'IntroCtrl',
  data: {
    isIntro: true
  },          
})

.state('main', {
  url: '/main',
  templateUrl: 'main.html',
  controller: 'MainCtrl',
  data: {
    isIntro: false
  },            
})
在ruote更改$stateChangeStart之前

我检查本地存储是否设置了visitedIntro字段。如果设置好,我会去主路线。

在您的介绍控制器中,您可以设置localstorage属性的值:

.controller('IntroCtrl', function($scope, $state, $ionicSlideBoxDelegate, $localStorage) {

  $scope.title = "<b>CUSTOM</b> TITLE";
  $scope.showIntro = true;

  // Called to navigate to the main app
  $scope.startApp = function() {
    $state.go('main');
  };
  $scope.next = function() {
    $ionicSlideBoxDelegate.next();
  };
  $scope.previous = function() {
    $ionicSlideBoxDelegate.previous();
  };

  // Called each time the slide changes
  $scope.slideChanged = function(index) {
    $scope.slideIndex = index;
    if (index === 2)
    {
      $localStorage.visitedIntro = true;
    }
  };

});

当用户滑动并到达最后一张幻灯片时,我设置了$localStorage.visitedIntro = true

if (index === 2)
{
   $localStorage.visitedIntro = true;
}

如果您想查看其工作原理,请查看完整示例here

当然这只是一个选择。您还可以使用ui-ruoter的解析。

<强>更新

奇怪的迭代是ui-ruoter的一个已知问题。您可以在SO上查看此question

您可以通过这种方式进行更改,并且可以正常工作:

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

我知道它不是很优雅,但至少它起作用 更新了plunker