2015-06-24 21 views
8

mam aplikację, która w zasadzie wygląda toNajlepsze praktyki dla animowanie wielu UI-widoki jako jeden

<div ui-view="header"> 
<div ui-view="main"> 
<div ui-view="footer"> 

Teraz stopka pozostanie taka sama dla wszystkich różnych stanach app, ale nagłówek zmieni w niektórych stanach, ale także udostępniać treści w wielu stanach. Jedynym ui-view, który zmieni się we wszystkich stanach jest ui-view="main".

Obecnie mój $stateProvider wygląda następująco (stopka jeszcze nie zaimplementowane):

app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) { 
    $stateProvider.state('root',{ 
     url: '', 
     abstract: true, 
     views: { 
     'header': { 
      templateUrl: appHelper.views+'/header.html', 
     }, 
     } 
    }) 
    .state('root.home', { 
     url: '/', 
     views: { 
     'header': { 
      templateUrl: appHelper.views+'/header.html', 
     }, 
     '[email protected]': { 
      templateUrl: appHelper.views+'/home.html', 
      controller: 'HomeController as homeVm', 
     } 
     }, 
     resolve: { 
     posts: function(dataService) { 
      return dataService.getPosts(); 
     }, 
     artists: function(dataService) { 
      return dataService.getArtists(); 
     } 
     } 
    }) 
    .state('root.artist', { 
     url: '/artist/:slug', 
     views: { 
     '[email protected]': { 
      templateUrl: appHelper.views+'/artistHeader.html', 
      controller: 'ArtistController as artistVm', 
     }, 
     '[email protected]': { 
      templateUrl: appHelper.views+'/artist.html', 
      controller: 'ArtistController as artistVm', 
     } 
     }, 
     resolve: { 
     artist: function($stateParams, dataService) { 
      return dataService.getArtist($stateParams.slug);  
     } 
     } 
    }); 
}]); 

Tak daleko, tak dobrze. Ale tutaj jest haczyk. Podczas przejść chcę animować wszystkie ui-view s jako jeden. Aby sprawić, że rzeczy wyglądają spójnie w moim przypadku (jest to animacja zanikania), chciałbym umieścić je w opakowaniu div i mieć ten blok, aby zanikło/zanikło (wykonanie go na każdym innym ui-view spowoduje wszelkiego rodzaju brzydotę).

Jaka jest najlepsza praktyka w tym scenariuszu?

Czy je zawinąć w ui-view i jakoś je podłączyć w $stateProvider (zagnieżdżone ui-view s?). Czy są na to inne sposoby? Czy mogę posłuchać $stateChange i zastosować klasy do mojego opakowania, takie jak ngAnimate przy pomocy ui-view? (zaniknij, a następnie poczekaj, aż całkowicie zniknie z pomyślnym rozwiązaniem, zanim zniknie).

Z moich wysiłków w googlowaniu wydaje się, że jest to szczególnie zalecane przy obsłudze animacji typu przejścia.

+0

Animacje w zdarzeniach '$ stateChangeStart' i' $ stateChangeSuccess' mają dziwne efekty uboczne, więc należy ich unikać (w tej chwili). Dopóki ui-router nie będzie miał lepszego sposobu na zarządzanie obietnicą przejścia niż animacja 'event.preventDefault()' przez JS będzie trudna. Uruchamianie trzech "ui-poglądów" i synchronizowanie ich wszystkich synchronicznie nie powinno stanowić problemu poprzez czysty CSS. Zajrzyj do sekcji Często zadawane pytania dla routery, znajduje się sekcja poświęcona animacji przejść. –

+0

Podczas gdy animacja rzeczywiście jest synchronicznie powoduje problem z projektem, jak "nagłówek" jest ustalona do górnej części widoku podczas przewijania. Kiedy zaniknie, pokaże się zawartość "głównego" pod spodem, która nie jest pożądana. Z opakowaniem oczywiście nie stanowi to problemu, ponieważ zniknie jak jeden element .. – INT

Odpowiedz

2

... Podczas przejść chcę animować wszystkie ui-widoki jako jedno. Aby sprawić, że rzeczy wyglądają spójnie w moim przypadku (jest to animacja zanikania), chciałbym, aby umieściło je w opakowaniu div i aby ten element działał, zanikanie/zanikanie (wykonanie tego w każdym innym widoku ui spowoduje rodzaje brzydoty ).

Jaka jest najlepsza praktyka w tym scenariuszu?

Wariant 1: Korzystanie haki zdarzeń $stateChangeStart i $stateChangeSuccess

Takie podejście ma pewne skutki uboczne, jak @David wspomniano w komentarzach. Unikaj tego, dopóki ui-router nie przedstawi lepszego sposobu na zarządzanie obietnicą zmiany stanu. Obecnie polega na event.preventDefault(), aby zapobiec zmianie.

Zasadniczo ui-router wyświetli Twój widok zmiany trasy ui-view w tym samym czasie, co widok wejścia przychodzącego. Tak więc otrzymujemy poprzedni model ui-view, który jest nadal widoczny podczas renderowania następnej wersji: ui-view. Jeśli animujesz widok, wówczas będzie istnieć czas przejścia nakładania się starego widoku na nowy. Powinieneś poprzestać na renderowaniu nowego widoku interfejsu, dopóki stary nie zakończy animacji (przed animacją nowego). Z podobnych powodów, zawijanie ich w innym ui-view i podłączenie ich do $stateProvider nie bądź mądry.

Opcja 2: (zalecane) CSS oparte animacje

Najczęściej iść z przejściami CSS na podstawie i można to osiągnąć albo przez

  • przypisywania wspólną klasę CSS do każdego ui-view i zastosowanie animacji na tej klasie.
  • lub dołączając trzy ui-view w <div> (jeśli naprawdę tego potrzebujesz) i zastosuj animację.

Tak czy inaczej, traktowałbyś wszystkie ui-views jako jedną całość, a ich animacja sprawiałaby, że rzeczy wyglądałyby bardziej spójnie.

HTML:

<div ui-view="header" ></div>  
<div ui-view="main" ></div> 
<div ui-view="footer" ></div> 

CSS:

[ui-view].ng-enter { 
    animation: fadein 2s; 
} 

@keyframes fadein { 
    from { opacity: 0; } 
    to { opacity: 1; } 
} 

Oto pracuje plunkr oparty na przypadku użycia gdzie mam stanie abstrakcyjny root i trzy stany zagnieżdżone root.home, root.artist i root.band. Podczas gdy ui-view='main' zmienia się we wszystkich stanach, ui-view='footer' nie zmienia żadnych i ui-view='header' zmian dla stanu "root.artist". Fakt, że używasz klas opartych na css .ng-enter i .ng-leave do wyzwalania animacji, technicznie przezwyciężysz problemy z poprzednim podejściem.

$stateProvider 
     .state('root',{ 
      abstract:true, 
      views:{ 
       'header':{ //absolutely targets the 'header' view in root unnamed state. 
       templateUrl:'header.html' 
       }, 
       'footer':{ //absolutely targets the 'footer' view in root unnamed state. 
       templateUrl:'footer.html' 
       } 
      } 
     }) 
     .state('root.home',{ 
      views:{ 
       '[email protected]':{ 
       templateUrl:'main.html' 
       }, 
      }   
     }) 
     .state('root.artist',{ 
      views:{ 
       '[email protected]':{ 
       templateUrl:'artist-header.html' 
       }, 
       '[email protected]':{ 
       templateUrl:'artist-main.html' 
       }, 
      }   
     }) 
     .state('root.band',{ 
      views:{ 
       '[email protected]':{ 
       templateUrl:'band-main.html' 
       }, 
      }   
     }) 
+0

Hej @NLN, dziękuję za wyczerpującą odpowiedź! Zaktualizowałem twój plunkr, aby lepiej odzwierciedlał problem, z którym się spotykam: http://plnkr.co/edit/mLUqKIjby9WGZ60k56ym?p=preview Z chwilą zanikania musisz również ustawić pozycję absolutną, co powoduje, że jest trochę trudne ze stopką. Dlatego chcę mieć możliwość animowania rodzica div, a nie poszczególnych div (jak widać, czerwone i niebieskie nakładki div, które w ogóle nie wyglądają dobrze, gdy pojawia się nieprzezroczystość). – INT