2016-04-26 19 views
9

मैं कोणीय 2 + Rx.JS 5/अगला का डेमो ऐप एक साथ रखने की कोशिश कर रहा हूं।हर बार जब मैं मार्ग बदलता हूं तो मेरे कोणीय 2 घटक फिर से तत्काल क्यों होते हैं?

मैंने देखा कि जब भी मैं मार्ग स्विच करता हूं तो मेरे घटकों को फिर से चालू किया जाता है।

import {Component} from 'angular2/core'; 
import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router'; 
import {FirstComponent} from './app.first-component.ts'; 
import {SecondComponent} from './app.second-component.ts'; 
import {AppService} from "./app.services.ts"; 


@Component({ 
    selector: 'my-app', 
    providers: [AppService, FirstComponent, SecondComponent], 
    directives: [FirstComponent, SecondComponent, ROUTER_DIRECTIVES], 
    template: `<h1>An Angular 2 App</h1> 
       <a [routerLink]="['First']">first-default</a> 
       <a [routerLink]="['Second']">second</a> 
       <router-outlet></router-outlet>` 
}) 
@RouteConfig([ 
    {path: '/', name: 'First', component: FirstComponent, useAsDefault: true}, 
    {path: '/second', name: 'Second', component: SecondComponent} 
]) 
export class AppComponent { 
} 

तो पहले घटक (/ को मैप किया) के लिए कोड:

import {bootstrap} from 'angular2/platform/browser'; 
import {HTTP_PROVIDERS} from 'angular2/http'; 
import {ROUTER_PROVIDERS} from 'angular2/router'; 
import {AppComponent} from './app.component.ts'; 

bootstrap(AppComponent, [HTTP_PROVIDERS, ROUTER_PROVIDERS]); 

यहाँ जड़ घटक के लिए कोड है:

यहाँ जड़ अनुप्रयोग के लिए कोड है

import {Component, OnInit, NgZone} from "angular2/core"; 
import {AppService} from "./app.services.ts"; 
import 'rxjs/Rx'; 


@Component({ 
    selector: 'my-first', 
    template: ` 
<div> 
    <ul> 
     <li *ngFor="#s of someStrings"> 
      a string: {{ s }} 
     </li> 
    </ul> 
</div>` 
}) 
export class FirstComponent implements OnInit { 

    zone:NgZone; 

    constructor(private appService:AppService) { 
     console.log('constructor', 'first'); 
     this.zone = new NgZone({enableLongStackTrace: false}); 
    } 

    someStrings:string[] = []; 

    ngOnInit() { 
     console.log('ngOnInit', 'first'); 
     this.appService.refCounted.subscribe(
      theStrings=> { 
       this.zone.run(() =>this.someStrings.push(...theStrings)); 
      }, 
      error=>console.log(error) 
     ); 
    } 
} 

और दूसरा घटक (/second पर मैप किया गया):

import {Component, OnInit, NgZone} from "angular2/core"; 
import {AppService} from "./app.services.ts"; 

@Component({ 
    selector: 'my-second', 
    template: ` 
<div> 
    <ul> 
     <li *ngFor="#s of someStrings"> 
      a string: {{ s }} 
     </li> 
    </ul> 
</div>` 
}) 
export class SecondComponent implements OnInit { 

    zone:NgZone; 

    constructor(private appService:AppService) { 
     console.log('constructor', 'second'); 
     this.zone = new NgZone({enableLongStackTrace: false}); 
    } 

    someStrings:string[] = []; 

    ngOnInit() { 
     console.log('ngOnInit', 'second'); 
     this.appService.refCounted.subscribe(
      theStrings=> { 
       this.zone.run(() =>this.someStrings.push(...theStrings)); 
      }, 
      error=>console.log(error) 
     ); 
    } 
} 

और अंत में अनुप्रयोग सेवा (थोड़ा कम इस सवाल के लिए प्रासंगिक):

import {Injectable} from "angular2/core"; 
import {Observable} from "rxjs/Observable"; 
import {Subject} from "rxjs/Subject"; 
import 'rxjs/Rx'; 


@Injectable() 
export class AppService { 

    constructor(){ 
     console.log('constructor', 'appService'); 
    } 

    someObservable$:Observable<string[]> = Observable.create(observer => { 
     const eventSource = new EventSource('/interval-sse-observable'); 
     eventSource.onmessage = x => observer.next(JSON.parse(x.data)); 
     eventSource.onerror = x => observer.error(console.log('EventSource failed')); 

     return() => { 
      eventSource.close(); 
     }; 
    }); 

    subject$ = new Subject(); 

    refCounted = this.someObservable$.multicast(this.subject$).refCount(); 

    someMethod_() { 
     let someObservable$:Observable<string[]> = Observable.create(observer => { 
      const eventSource = new EventSource('/interval-sse-observable'); 
      eventSource.onmessage = x => observer.next(JSON.parse(x.data)); 
      eventSource.onerror = x => observer.error(console.log('EventSource failed')); 

      return() => { 
       eventSource.close(); 
      }; 
     }); 
     return someObservable$; 
    } 
} 

तो आदेश First और Second घटकों के इन्स्टेन्शियशन डिबग करने में, मैं में एक console.log जोड़ लिया है कंस्ट्रक्टर्स/ngOnInit:

और मैंने देखा है कि हर बार जब मैं लिंक पर क्लिक करके मार्ग बदलने के लिए, मैं:

constructor first 
ngOnInit first 

constructor second 
ngOnInit second 
... 

क्या कोई सलाह दे सकता है कि यह व्यवहार की उम्मीद है या नहीं? यदि ऐसा है तो मैं केवल एक बार अपने घटकों को तुरंत चालू करने के लिए Angular2 कैसे प्राप्त कर सकता हूं?

ध्यान दें कि मुझे स्पष्ट रूप से आवश्यक है कि First और Second घटकों को providers सरणी जोड़कर रूट-स्तर घटक पर तुरंत चालू किया जाए।

पीएस https://github.com/balteo/demo-angular2-rxjs/tree/WITH-ROUTER

संपादित:

मैं अब भी इस समस्या का समाधान खोजने के लिए कोशिश कर रहा हूँ यहाँ इस परियोजना के लिए GitHub भंडार है। मुझे राउटर या मेरे घटकों के साथ कुछ गड़बड़ हो रही है। मैंने ऐप को here पर गिटब को धक्का दिया है कि कोई सलाह दे सकता है।

+0

क्या आपको अपना समाधान मिला? –

उत्तर

6

> = 2.3.0-rc.0

एक कस्टम RouteReuseStrategy जब कराई घटकों को नष्ट कर दिया और निर्मित या पुन: उपयोग किया जाता है को नियंत्रित करने के लागू किया जा सकता।

> = 2.0।0

CanReuse नए राउटर में अब मौजूद नहीं है। जब एक ही मार्ग पर रहते हुए केवल मार्ग पैरामीटर बदलते हैं, तो घटक पुन: निर्मित नहीं होता है।

यदि मार्ग बदल दिया गया है और उसी घटक पर वापस नेविगेट किया गया है तो घटक को फिर से बनाया गया है।

< = RC.x

ध्यान दें कि मैं स्पष्ट रूप से आवश्यक है कि पहले और दूसरे घटक वहाँ एक प्रदाताओं सरणी जोड़कर रूट स्तर घटक पर instantiated जा।

providers: [] पर घटकों को जोड़ना ज्यादातर इस मुद्दे के संबंध में अधिक अर्थहीन है।

आप अपने घटक के

routerCanReuse(next: ComponentInstruction, prev: ComponentInstruction) { return true; } 

जोड़कर CanReuse

लागू कर सकते हैं, लेकिन यह काफी सीमित है नेविगेशन किस तरह के लिए एक ही उदाहरण पुन: उपयोग किया जाता है (यदि आप एक ही मार्ग है और केवल परिवर्तन पर रहने पैरामीटर)।

यदि CanReuse आपकी समस्या को ठीक नहीं करता है तो डेटा को एक सेवा में ले जाएं, जहां उदाहरण रखा जाता है और घटक को वर्तमान डेटा दिखाने के लिए इस सेवा के डेटा में घटक के दृश्य को बाध्य करता है।

+1

धन्यवाद बहुत गुंटर, मैं दूसरे समाधान को लागू करने की कोशिश कर रहा हूं (डेटा को सेवा में ले जा रहा हूं)। जब मैं इसे काम करने में कामयाब रहा हूं तो मैं जवाब स्वीकार करूंगा। – balteo

+0

मैंने एक और पोस्ट खोला है जो मूल पोस्ट से संबंधित है। Http://stackoverflow.com/questions/36866215 – balteo

+0

मैंने डेटा को सेवा में रखा है लेकिन इस तथ्य के कारण कि मैं एक ईवेंटसोर्स का उपयोग करता हूं और यह कि प्रत्येक मार्ग परिवर्तन पर घटकों को फिर से चालू किया जाता है, यह अभी भी काम नहीं कर रहा है। .. मेरा संपादन देखें। – balteo

2

यह पूरी तरह से अपेक्षित व्यवहार है कि घटकों का निर्माण और आपके मार्ग परिवर्तन के रूप में नष्ट हो जाएगा।

याद रखें, घटक आपके टेम्पलेट्स के DOM तत्वों से निकटता से जुड़े हुए हैं। चूंकि इन डोम तत्वों को हटा दिया जाता है या बदला जाता है, इसलिए घटक को नष्ट किया जाना चाहिए और एक नया निर्माण किया जाना चाहिए।

इसके कुछ अपवाद भी हैं, लेकिन नहीं के रूप में यह अपने यूज-केस से संबंधित है (उदाहरण के लिए CanReuse विधि एक और जवाब में बताया गया है, लेकिन है कि कुछ पूरी तरह से अलग के लिए है।

क्या CanReuse करता है, है जब एक मार्ग से जा रहा एक और मार्ग (route2) से (इसे route1 कॉल), और दोनों मार्गों, एक ही घटक MyComponent उपयोग करें यदि आप यह बता यह घटक का फिर से उपयोग करने की अनुमति दी है कि, यह मूल रूप से कह रहा है:

"जिस मार्ग से मैं जा रहा हूं, वैसे ही उसी घटक प्रकार का उपयोग करता है जिस मार्ग पर मैं cur हूं किराए पर, नए मार्ग पर मेरे वर्तमान घटक उदाहरण का पुन: उपयोग करना ठीक है "(शायद क्योंकि यह उदाहरण के लिए स्टेटलेस है)।

आप बिल्कुल नहीं कहें कि आप क्या हासिल करने की कोशिश कर रहे हैं, या आपके दो घटकों के लिए केवल एक बार तत्काल क्यों होना महत्वपूर्ण है, लेकिन आम तौर पर, घटक दीर्घकालिक आवेदन स्थिति (या अधिक सटीक, राज्य जो घटक से जुड़े डोम तत्व के जीवनकाल को पार करता है)। इस तरह की चीजें कहीं और रहनी चाहिए (जैसे सेवाओं में) और इंजेक्शन के माध्यम से घटकों के बीच साझा (या इनपुट के रूप में पारित)।

1

"यह पूरी तरह से अपेक्षित व्यवहार है कि घटक निर्माण किया जाएगा और अपने मार्ग में परिवर्तन के रूप विलुप्त"

मुद्दा यह है कि घटक बार-बार नहीं पुनर्निर्मित किया जाना चाहिए एक दो लिंक के बीच आगे पीछे नेविगेट करता है के रूप में (जो है एक दूसरे से अलग हैं)। क्या होगा यदि आपके पास जटिल ग्राफिक्स और राज्य है कि आप एक लिंक पर संशोधन कर रहे हैं और ऑब्जेक्ट नष्ट हो गया है और फिर से बनाया गया है जब आप अपने काम को फिर से शुरू करने के लिए वापस आते हैं?

वस्तुओं को नष्ट किया जाना चाहिए और बार-बार पुनर्निर्मित किया जाना चाहिए यदि एक ढांचे को निर्देशित नहीं किया जाना चाहिए। यह दोनों विकल्पों को प्रदान करेगा और डिफ़ॉल्ट विकल्प में, इसे नष्ट और पुन: बनाना नहीं चाहिए क्योंकि यह अंतर्ज्ञानी व्यवहार है। यह वही व्यवहार है जो अधिकांश यूआई ढांचे का उपयोग वर्षों से किया जाता है।

संबंधित मुद्दे