2016-09-21 20 views
6

में काम नहीं करेगा मेरे पास Angular2- आधारित क्लाइंट पक्ष के साथ एक एप्लिकेशन है।कोणीय 2 @ होस्टलिस्टर व्युत्पन्न घटक

abstract class BaseClass { 
    @HostListener('window:beforeunload') beforeUnloadHandler() { 
     console.log('bla'); 
    } 
} 

और दो बहुत ही एक दूसरे को व्युत्पन्न वर्ग के समान:

@Component({ 
    selector: 'derived-one', 
    templateUrl: './templates/app/+derived-one/derived-one.component.html' 
}) 
export class DerivedOne extends BaseClass { 
} 

@Component({ 
    selector: 'derived-two', 
    templateUrl: './templates/app/+derived-two/derived-two.component.html' 
}) 
export class DerivedTwo extends BaseClass { 
} 

समस्या यह है कि, उदाहरण के लिए, DerivedOne में beforeUnloadHandler ठीक है, जबकि DerivedTwo में काम करता है यह नहीं करता है मैं एक आधार वर्ग है बिल्कुल एक कॉल प्राप्त नहीं है।

मुझे पता है कि यह उपरोक्त जानकारी को देखने के कारण क्यों है, लेकिन शायद किसी को संदेह हो सकता है कि इस तरह के अजीब व्यवहार का कारण क्या हो सकता है।

कुछ और सूचनाएं:

अगर मैं निम्नलिखित का उपयोग करें:

abstract class BaseClass 
    constructor(){ 
     window.onbeforeunload = function(){ 
      console.log('bla'); 
     } 
    } 
} 

सब कुछ ठीक काम करता है, लेकिन मैं अभी भी एक Angular2 आधारित समाधान खोजने के लिए चाहते हैं;

अगर मैं लिखना

abstract class BaseClass { 
    beforeUnloadHandler() { 
     console.log('bla'); 
    } 
} 

और में derived-two.component.html

<div (window.beforeunload)="beforeUnloadHandler()"></div> 

सब कुछ भी ठीक काम करता है, लेकिन यह एक बदसूरत हैक की तरह दिखता है;

फिर, अगर मैं लिखने

abstract class BaseClass { 
    beforeUnloadHandler() { 
     console.log('bla'); 
    } 
} 

और

@Component({ 
    selector: 'derived-two', 
    host: {'window:beforeunload': 'beforeUnloadHandler' } 
    templateUrl: './templates/app/+derived-two/derived-two.component.html' 
}) 
export class DerivedTwo extends BaseClass { 
} 

यह काम नहीं करेगा।

अंत में, अगर मैं और DerivedOne में उपयोग करता हूं, तो यह काम करता है, लेकिन मैं डुप्लिकेट कोड का उपयोग करने से बचना चाहता हूं।

उम्मीद है कि ऊपर दी गई जानकारी के साथ काम करने के लिए पर्याप्त होगा (कम से कम कुछ अनुमान लगाने के लिए)।

+1

कृपया, स्पष्ट करें कि कक्षा के लिए सही तरीके से व्यवहार करने की शर्तें क्या हैं। क्या व्युत्पन्न है जो काम नहीं करता है? क्या घटक एक साथ उपयोग में उपयोग किए जाते हैं? क्या यह उस क्रम पर निर्भर करता है जिसमें वे आयात किए जाते हैं या जिस क्रम में वे दिखाई देते हैं? – estus

उत्तर

8

अद्यतन 2.3.0

अब आप घटकों के लिए वस्तु विरासत का लाभ ले सकते हैं।

अधिक जानकारी आप इस में देख सकते हैं प्रतिबद्ध https://github.com/angular/angular/commit/f5c8e0989d85bc064f689fc3595207dfb29413f4

पुराने संस्करण

1) आप एक वर्ग है, तो:

abstract class BaseClass { 
    @HostListener('window:beforeunload') beforeUnloadHander() { 
    console.log('bla'); 
    } 
} 

तो यह काम करेंगे

Plunker Example (कहीं सफेद जगह डालें Issue with binding and @ViewChild

लेकिन यह अभी स्पष्ट नहीं क्यों @HostListener साथ समाधान में काम नहीं किया - संपादक और घड़ी कंसोल)

लेकिन में सावधानके बाद से Angular2 पूर्ण विरासत का समर्थन नहीं करता हो पहली जगह

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

abstract class BaseClass { 
    @HostListener('window:beforeunload') beforeUnloadHander() { 
    console.log(`bla-bla from${this.constructor.name}`); 
    } 
} 

@Component({ 
    selector: 'derived-one', 
    template: '<h2>derived-one</h2>' 
}) 
export class DerivedOne extends BaseClass { 
    @Input() test; 
} 

Plunker

यह जावास्क्रिप्ट की तरह करने के लिए परिवर्तित हो जाएगा:

var core_1 = require('@angular/core'); 
var BaseClass = (function() { 
    function BaseClass() { 
    } 
    BaseClass.prototype.beforeUnloadHander = function() { 
     console.log("bla-bla from" + this.constructor.name); 
    }; 
    __decorate([ 
     core_1.HostListener('window:beforeunload'), 
     __metadata('design:type', Function), 
     __metadata('design:paramtypes', []), 
     __metadata('design:returntype', void 0) 
    ], BaseClass.prototype, "beforeUnloadHander", null); 
    return BaseClass; 
}()); 
var DerivedOne = (function (_super) { 
    __extends(DerivedOne, _super); 
    function DerivedOne() { 
     _super.apply(this, arguments); 
    } 
    __decorate([ 
     core_1.Input(), 
     __metadata('design:type', Object) 
    ], DerivedOne.prototype, "test", void 0); 
    DerivedOne = __decorate([ 
     core_1.Component({ 
      selector: 'derived-one', 
      template: '<h2>derived-one</h2>' 
     }), 
     __metadata('design:paramtypes', []) 
    ], DerivedOne); 
    return DerivedOne; 
}(BaseClass)); 

हम निम्नलिखित लाइनों में रुचि रखते हैं:

उदाहरण के लिए मान लीजिए कि हम निम्न कोड डालते हैं
__decorate([ 
    core_1.HostListener('window:beforeunload'), 
     __metadata('design:type', Function), 
     __metadata('design:paramtypes', []), 
     __metadata('design:returntype', void 0) 
], BaseClass.prototype, "beforeUnloadHander", null); 

... 
__decorate([ 
    core_1.Input(), 
    __metadata('design:type', Object) 
], DerivedOne.prototype, "test", void 0); 

HostListener और Input संपत्ति सजावटकर्ता हैं (propMetadata कुंजी)।इस तरह से दो मेटाडाटा प्रविष्टियों परिभाषित करेगा - अंत में जब angular2 DerivedOne वर्ग से मेटाडेटा निकालने जाएगा यह केवल अपने स्वयं के मेटाडाटा का उपयोग करेगा BaseClass पर और DerivedOne enter image description here enter image description here

पर:

enter image description here

सभी प्राप्त करने के लिए मेटाडेटा आप कस्टम सजावट लिख सकते हैं जैसे:

function InheritPropMetadata() { 
    return (target: Function) => { 
    const targetProps = Reflect.getMetadata('propMetadata', target); 

    const parentTarget = Object.getPrototypeOf(target.prototype).constructor; 
    const parentProps = Reflect.getMetadata('propMetadata', parentTarget); 

    const mergedProps = Object.assign(targetProps, parentProps); 

    Reflect.defineMetadata('propMetadata', mergedProps, target); 
    }; 
}; 

@InheritPropMetadata() 
export class DerivedOne extends BaseClass { 

यहाँ एक काम demo

2) यदि आप इस प्रकार किया:

abstract class BaseClass 
    constructor(){ 
    window.onbeforeunload = function(){ 
     console.log('bla'); 
    }; 
    } 
} 

तो यह केवल एक बार क्योंकि आप window.onbeforeunload हैंडलर अधिभावी रहे हैं हर आप निम्न बजाय का उपयोग करना चाहिए द्वारा सक्रिय किया जाएगा:

abstract class BaseClass { 
constructor(){ 
    window.addEventListener('beforeunload',() =>{ 
     console.log(`bla-bla from${this.constructor.name}`); 
    }) 
    } 
} 

Plunker Example

3) अंत में अगर आप आधार वर्ग के रूप में नीचे देख सकते हैं:

host: {'(window:beforeunload)': 'beforeUnloadHander()' } 
:

abstract class BaseClass { 
    beforeUnloadHander() { 
    console.log(`bla-bla from${this.constructor.name}`); 
    } 
} 

तो आप सही सिंटैक्स (उपयोग करने के लिए आप डेकोरेटर संपत्ति में कोष्ठक भूल रहे हैं) है

Plunker Example

आशा है कि यह आपकी मदद करे!

+1

धन्यवाद, दयालु महोदय, यह वास्तव में मदद की! मैंने तीसरा विकल्प चुना, वैसे भी (मुझे अभी भी विश्वास नहीं है कि मैंने सिंटैक्स गलती की है)। लेकिन यह अभी भी स्पष्ट नहीं है कि '@ होस्टलिस्टर 'के साथ समाधान पहले स्थान पर क्यों नहीं काम करता था। –

+1

मैंने थोड़ा सा जवाब अपडेट किया है। – yurzui

+0

वाह, यह वास्तव में सहायक था! काश मैं तुम्हारा जवाब दो बार पसंद कर सकता हूं: डी –

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