2015-11-05 17 views
25

Trong Angular 1.x chúng ta có thể sử dụng ngAnimate để phát hiện khi chúng ta đang đi hoặc vào một tuyến đường cụ thể. Bên cạnh đó chúng tôi có thể áp dụng các hành vi đối với họ:Hình động chuyển tiếp trang với giao diện bộ định tuyến và thành phần Angular 2.0 hứa hẹn

animateApp.animation('.myElement', function(){ 

    return { 

     enter : function(element, done) { 
      //Do something on enter 
     }, 

     leave : function(element, done) { 
      //Do something on leave 
     } 
    }; 

)}; 

Hệ quả là một sản phẩm như thế này: http://embed.plnkr.co/uW4v9T/preview

Tôi muốn làm điều gì đó tương tự với góc 2,0 và tôi cảm thấy như tôi là khá chặt chẽ .. Vì vậy, ở đây, tôi đã tạo một bộ định tuyến đơn giản trong thành phần ứng dụng chính điều khiển điều hướng giữa các thành phần nhàvề các thành phần.

import { bootstrap, bind, Component, provide, View } from 'angular2/angular2'; 
import {RouteConfig, RouteParams, ROUTER_DIRECTIVES, ROUTER_PROVIDERS, APP_BASE_HREF, ROUTER_BINDINGS} from 'angular2/router' 




///////////////////////////////////////////////////////////////// 
// Home Component Start 
///////////////////////////////////////////////////////////////// 
@Component({ 
    selector: 'home-cmp' 
}) 

@View({ 
    template: ` 
    <h2 class="title">Home Page</h2> 
    ` 
}) 

class HomeCmp implements OnActivate, onDeactivate{ 

    onActivate(next: ComponentInstruction, prev: ComponentInstruction) { 
    console.log("Home Page - initialized"); 
    } 

    onDeactivate(next: ComponentInstruction, prev: ComponentInstruction) { 
    console.log("Home Page - destroyed"); 
    } 

} 
///////////////////////////////////////////////////////////////// 
// Home Component End 
///////////////////////////////////////////////////////////////// 




///////////////////////////////////////////////////////////////// 
// About Component Start 
///////////////////////////////////////////////////////////////// 
@Component({ 
    selector: 'about-cmp' 
}) 

@View({ 
    template: ` 
    <h2 class="title">About Page</h2> 
    ` 
}) 

class AboutCmp implements OnActivate, onDeactivate { 

    onActivate(next: ComponentInstruction, prev: ComponentInstruction) { 
    console.log("About Page - initialized"); 
    } 

    onDeactivate(next: ComponentInstruction, prev: ComponentInstruction) { 
    console.log("About Page - destroyed"); 
    } 

} 
///////////////////////////////////////////////////////////////// 
// About Component End 
///////////////////////////////////////////////////////////////// 




///////////////////////////////////////////////////////////////// 
// Main Application Componenent Start 
///////////////////////////////////////////////////////////////// 
@Component({ 
    selector: 'my-app' 
}) 

@View({ 
    template: ` 
    <div> 
     <h1>Hello {{message}}!</h1> 
     <a [router-link]="['./HomeCmp']">home</a> 
     <a [router-link]="['./AboutCmp']">about</a> 
     <hr> 
     <router-outlet></router-outlet> 
    </div> 
    `, 
    directives: [ROUTER_DIRECTIVES] 
}) 

@RouteConfig([ 
    {path: '/', component: HomeCmp, as: 'HomeCmp'}, 
    {path: '/about', component: AboutCmp, as: 'AboutCmp'} 
]) 

export class App { 
} 
///////////////////////////////////////////////////////////////// 
// Main Application Componenent End 
///////////////////////////////////////////////////////////////// 




bootstrap(App, [ 
    ROUTER_BINDINGS, 
    ROUTER_PROVIDERS, 
    ROUTER_DIRECTIVES, 
    provide(APP_BASE_HREF, {useValue: '/'}) 
]) 

Hiện tại tôi có thể chụp khi bộ định tuyến đã khởi tạo hoặc hủy một thành phần cụ thể khi nó chuyển từ thành phần này sang bước kế tiếp. Điều này thật tuyệt, nhưng khi thành phần trước đó là bị phá hủy Tôi không thể áp dụng hình động chuyển tiếp trước khi thành phần tiếp theo được khởi tạo.

class HomeCmp implements OnActivate, onDeactivate{ 

    onActivate(next: ComponentInstruction, prev: ComponentInstruction) { 
     //This works 
     TweenMax.fromTo($(".title"), 1, {opacity: 0}, {opacity: 1}); 
    } 

    onDeactivate(next: ComponentInstruction, prev: ComponentInstruction) { 
     //This get ignored 
     TweenMax.fromTo($(".title"), 1, {opacity: 0}, {opacity: 1}); 
    } 

} 

Dường như có giải pháp cho việc sử dụng lời hứa này. Bản xem trước API của Angular.io họ tuyên bố:

Nếu onDeactivate trả về lời hứa, thay đổi tuyến đường sẽ đợi cho đến khi lời hứa kết thúc.

Nếu onActivate trả về một lời hứa, sự thay đổi tuyến đường sẽ đợi cho đến khi lời hứa giải quyết nhanh chóng và kích hoạt các thành phần con.

https://angular.io/docs/ts/latest/api/

Tôi siêu thương hiệu mới để lời hứa vì vậy tôi nghiền này lại với nhau thành mã của tôi mà giải quyết vấn đề của thành phần hiện tại của tôi bị phá hủy trên khởi của người tiếp theo, nhưng sau đó nó bao giờ bị tiêu diệt , nó chỉ tạo ra một thể hiện mới của nó. Mỗi khi tôi điều hướng trở lại nó, nó sẽ tạo ra một cá thể mới dẫn đến nhiều bản sao.

onDeactivate(next: ComponentInstruction, prev: ComponentInstruction) { 

    function ani(){ 
     TweenMax.fromTo($(".title"), 1, {opacity: 1}, {opacity: 0}); 
    } 

    var aniPromise = ani(); 

    aniPromise.then(function (ani) { 
     ani(); 
    }); 

} 

Vì vậy, để tóm tắt, router sẽ có thể chờ đợi các thành phần hiện tại để kết thúc nó kinh doanh trước khi phá hủy nó và khởi tạo các thành phần tiếp theo.

Tôi hy vọng rằng tất cả đều có ý nghĩa và tôi thực sự đánh giá cao sự trợ giúp!

Trả lời

13

Khi bạn trích dẫn từ tài liệu, nếu bất kỳ móc nào trả về Lời hứa, nó sẽ đợi cho đến khi hoàn thành để chuyển sang tài liệu tiếp theo, vì vậy bạn có thể dễ dàng trả lại Lời hứa về cơ bản. nhiều khi bạn cần).

onActivate(next: ComponentInstruction, prev: ComponentInstruction) { 
    TweenMax.fromTo($(".title"), 1, {opacity: 0}, {opacity: 1}); 
    return new Promise((res, rej) => setTimeout(() => res(1), 1000)); 
    } 

    onDeactivate(next: ComponentInstruction, prev: ComponentInstruction) { 
    TweenMax.fromTo($(".title"), 1, {opacity:1}, {opacity: 0}); 
    return new Promise((res, rej) => setTimeout(() => res(1), 1000)); 
    } 

Lưu ý rằng tôi trở lại một Promise mà chạy một setTimeout.Chúng tôi chờ một chút để cung cấp thời gian hoạt ảnh đủ để hoàn thành.

Tôi thực sự không thích sử dụng setTimeouts, vì vậy chúng tôi cũng có thể sử dụng Observables, cá nhân tôi thích nhất.

return Rx.Observable.of(true).delay(1000).toPromise(); 

Ở đây tôi chuyển một giá trị ngẫu nhiên (đúng trong trường hợp này) và trì hoãn giá trị này một giây và cuối cùng truyền cho lời hứa. Có, nó kết thúc là một Promise nhưng tôi không sử dụng nó trực tiếp.

Dưới đây là plnkr với ví dụ hoạt động (hy vọng là những gì bạn đang tìm kiếm).

PS: Nếu đôi khi nó phàn nàn về việc nó không thể tìm thấy đường dẫn đến Rx, hãy tiếp tục làm mới cho đến khi nó hoạt động (tôi đã thêm Rx.js theo cách thủ công và hơi nặng nề cho plnkr apprently).

+0

bạn sẽ nhận được lời cảm ơn nhanh chóng và toàn diện! – SimonHawesome

+0

Vui vì nó đã hoạt động :) –

+0

Trả lời tuyệt vời! Tôi tự hỏi nếu có một cách để "chồng lên nhau" các hình ảnh động. Dường như với tôi rằng nó sẽ không dễ dàng như các thành phần đầu tiên nên được ẩn (vô hiệu hóa) để hiển thị (kích hoạt) khác. Có suy nghĩ gì không? –

9

góc 2 giải pháp cuối cùng:

plunk

Tóm lại, chúng ta có thể sử dụng @routeAnimation built-in chỉ thị để đạt được điều này. Mỗi thành phần của chúng tôi đại diện cho một tuyến đường dành cho trẻ em sẽ được trang trí với một cái gì đó như:

@Component({ 
    selector: 'app-pageone' 
    host: { '[@routeAnimation]': 'true' }, 
    styles: [':host { width: 300px; display: block; position: absolute; }'] 
    animations: [ 
    trigger('routeAnimation', [ 
     state('*', style({transform: 'translateX(0)', opacity: 1})), 
     transition('void => *', [ 
     style({transform: 'translateX(-100%)', opacity: 0}), 
     animate('0.5s cubic-bezier(0.215, 0.610, 0.355, 1.000)') 
     ]), 
     transition('* => void', 
     animate('0.5s cubic-bezier(0.215, 0.610, 0.355, 1.000)', style({ 
      transform: 'translateX(100%)', 
      opacity: 0 
     })) 
    ) 
    ]) 
    ] 
}) 
+0

'kiểu: [': máy chủ {chiều rộng: 300px; display: block; vị trí: tuyệt đối; } '] 'bit là rất cần thiết, đã gặp khó khăn nhận được của tôi cho đến khi tôi thấy điều này, cảm ơn! – James

+2

Thay vì sử dụng kiểu trên mọi thành phần, bạn cũng có thể đặt kiểu này vào css: 'router-outlet + * { position: absolute; chiều rộng: 100%; } ' – LVDM

+0

Có thể thực hiện nó mà không có' vị trí: tuyệt đối; '? Bởi vì vị trí tuyệt đối phá vỡ phong cách ban đầu của tôi. Cảm ơn! –

Các vấn đề liên quan