"यदि कोई कर्मचारी अपना काम अच्छी तरह से करना चाहता है, तो उसे पहले अपने औजारों को तेज करना होगा।" - कन्फ्यूशियस, "द एनालेक्ट्स ऑफ कन्फ्यूशियस। लू लिंगगोंग"
मुखपृष्ठ > प्रोग्रामिंग > एंगुलर लैब: आइए एक दृश्यता निर्देश बनाएं

एंगुलर लैब: आइए एक दृश्यता निर्देश बनाएं

2024-11-03 को प्रकाशित
ब्राउज़ करें:133

Angular LAB: let

इस लेख में मैं यह बताने जा रहा हूं कि एक बहुत ही सरल कोणीय निर्देश कैसे बनाया जाए जो किसी तत्व की दृश्यता स्थिति, या दूसरे शब्दों में, जब वह अंदर और बाहर जाता है, पर नज़र रखता है व्यूपोर्ट. मुझे आशा है कि यह एक अच्छा और शायद उपयोगी अभ्यास होगा!

ऐसा करने के लिए, हम इंटरसेक्शनऑब्जर्वर जावास्क्रिप्ट एपीआई का उपयोग करने जा रहे हैं जो आधुनिक ब्राउज़रों में उपलब्ध है।

हम क्या हासिल करना चाहते हैं

हम इस तरह निर्देश का उपयोग करना चाहते हैं:

I'm being observed! Can you see me yet?

  • दृश्यता हमारे कस्टम निर्देश का चयनकर्ता है
  • विजिबिलिटी मॉनिटर एक वैकल्पिक इनपुट है जो निर्दिष्ट करता है कि तत्व का अवलोकन करते रहना है या नहीं (यदि गलत है, तो व्यूपोर्ट में प्रवेश करने पर निगरानी बंद कर दें)
  • दृश्यता परिवर्तन हमें सूचित करेगा

आउटपुट इस आकार का होगा:

type VisibilityChange =
  | {
      isVisible: true;
      target: HTMLElement;
    }
  | {
      isVisible: false;
      target: HTMLElement | undefined;
    };

अपरिभाषित लक्ष्य होने का मतलब होगा कि तत्व को DOM से हटा दिया गया है (उदाहरण के लिए, @if द्वारा)।

निर्देश का निर्माण

हमारा निर्देश केवल एक तत्व की निगरानी करेगा, यह DOM संरचना को नहीं बदलेगा: यह एक विशेषता निर्देश होगा।

@Directive({
  selector: "[visibility]",
  standalone: true
})
export class VisibilityDirective implements OnInit, OnChanges, AfterViewInit, OnDestroy {
  private element = inject(ElementRef);

  /**
   * Emits after the view is initialized.
   */
  private afterViewInit$ = new Subject();

  /**
   * The IntersectionObserver for this element.
   */
  private observer: IntersectionObserver | undefined;

  /**
   * Last known visibility for this element.
   * Initially, we don't know.
   */
  private isVisible: boolean = undefined;

  /**
   * If false, once the element becomes visible there will be one emission and then nothing.
   * If true, the directive continuously listens to the element and emits whenever it becomes visible or not visible.
   */
  visibilityMonitor = input(false);

  /**
   * Notifies the listener when the element has become visible.
   * If "visibilityMonitor" is true, it continuously notifies the listener when the element goes in/out of view.
   */
  visibilityChange = output();
}

ऊपर दिए गए कोड में आप देखते हैं:

  • जिस इनपुट और आउटपुट के बारे में हमने पहले बात की थी
  • एक संपत्ति जिसे AfterViewInit$ (एक ऑब्जर्वेबल) कहा जाता है, जो ngAfterViewInit जीवनचक्र हुक के प्रतिक्रियाशील समकक्ष के रूप में कार्य करेगी
  • ऑब्जर्वर नामक एक संपत्ति जो हमारे तत्व की निगरानी के प्रभारी इंटरसेक्शनऑब्जर्वर को संग्रहीत करेगी
  • isVisibile नामक एक संपत्ति जो अंतिम दृश्यता स्थिति को संग्रहीत करेगी, ताकि एक ही स्थिति को लगातार दो बार उत्सर्जित करने से बचा जा सके

और स्वाभाविक रूप से, हम DOM तत्व को हथियाने के लिए ElementRef को इंजेक्ट करते हैं, जिस पर हम अपना निर्देश लागू करते हैं।

मुख्य विधि लिखने से पहले, आइए निर्देश के जीवनचक्र का ध्यान रखें।

ngOnInit(): void {
  this.reconnectObserver();
}

ngOnChanges(): void {
  this.reconnectObserver();
}

ngAfterViewInit(): void {
  this.afterViewInit$.next();
}

ngOnDestroy(): void {
  // Disconnect and if visibilityMonitor is true, notify the listener
  this.disconnectObserver();
  if (this.visibilityMonitor) {
    this.visibilityChange.emit({
      isVisible: false,
      target: undefined
    });
  }
}

private reconnectObserver(): void {}
private disconnectObserver(): void {}

अब यहाँ क्या होता है:

  • ngOnInit और ngOnChanges दोनों के अंदर हम पर्यवेक्षक को पुनरारंभ करते हैं। यह निर्देश को प्रतिक्रियाशील बनाने के लिए है: यदि इनपुट बदलता है, तो निर्देश अलग तरह से व्यवहार करना शुरू कर देगा। ध्यान दें, भले ही ngOnChanges ngOnInit से पहले चलता हो, फिर भी हमें ngOnInit की आवश्यकता है क्योंकि ngOnChanges टेम्पलेट में कोई इनपुट नहीं होने पर नहीं चलता है!
  • जब दृश्य प्रारंभ हो जाता है तो हम विषय को ट्रिगर करते हैं, हम कुछ ही सेकंड में इस पर पहुंच जाएंगे
  • मेमोरी लीक से बचने के लिए जब निर्देश नष्ट हो जाता है तो हम अपने पर्यवेक्षक को डिस्कनेक्ट कर देते हैं। अंत में, यदि डेवलपर ने इसके लिए कहा, तो हम सूचित करते हैं कि तत्व को एक अपरिभाषित तत्व उत्सर्जित करके DOM से हटा दिया गया है।

इंटरसेक्शनऑब्जर्वर

यह हमारे निर्देश का मूल है। हमारी रीकनेक्टऑब्जर्वर विधि अवलोकन शुरू करने वाली होगी! यह कुछ इस तरह होगा:

private reconnectObserver(): void {
    // Disconnect an existing observer
    this.disconnectObserver();
    // Sets up a new observer
    this.observer = new IntersectionObserver((entries, observer) => {
      entries.forEach(entry => {
        const { isIntersecting: isVisible, target } = entry;
        const hasChangedVisibility = isVisible !== this.isVisible;
        const shouldEmit = isVisible || (!isVisible && this.visibilityMonitor);
        if (hasChangedVisibility && shouldEmit) {
          this.visibilityChange.emit({
            isVisible,
            target: target as HTMLElement
          });
          this.isVisible = isVisible;
        }
        // If visilibilyMonitor is false, once the element is visible we stop.
        if (isVisible && !this.visibilityMonitor) {
          observer.disconnect();
        }
      });
    });
    // Start observing once the view is initialized
    this.afterViewInit$.subscribe(() => {
        this.observer?.observe(this.element.nativeElement);
    });
  }

मेरा विश्वास करें, यह उतना जटिल नहीं है जितना लगता है! यहाँ तंत्र है:

  • यदि ऑब्जर्वर पहले से ही चल रहा है तो सबसे पहले हम उसे डिस्कनेक्ट कर देते हैं
  • हम एक इंटरसेक्शनऑब्जर्वर बनाते हैं और उसके व्यवहार को परिभाषित करते हैं। प्रविष्टियों में मॉनिटर किए गए तत्व शामिल होंगे, इसलिए इसमें हमारा तत्व शामिल होगा। संपत्ति isIntersecting इंगित करेगी कि क्या तत्व की दृश्यता बदल गई है: हम इसकी तुलना पिछली स्थिति (हमारी संपत्ति) से करते हैं और यदि यह देय है, तो हम उत्सर्जन करते हैं। फिर हम नए राज्य को बाद के लिए अपनी संपत्ति में संग्रहीत करते हैं।
  • यदि दृश्यता मॉनिटर गलत है, तो जैसे ही तत्व दृश्यमान हो जाता है हम पर्यवेक्षक को डिस्कनेक्ट कर देते हैं: इसका काम पूरा हो गया है!
  • फिर हमें अपने तत्व को पार करके पर्यवेक्षक को शुरू करना होगा, इसलिए ऐसा करने के लिए हम अपने दृश्य के आरंभ होने की प्रतीक्षा करते हैं।
अंत में, आइए उस विधि को लागू करें जो पर्यवेक्षक को डिस्कनेक्ट कर देती है, आसान है:


निजी डिस्कनेक्टऑब्जर्वर(): शून्य { यदि (यह.पर्यवेक्षक) { this.observer.disconnect(); यह.पर्यवेक्षक = अपरिभाषित; } }
 private disconnectObserver(): void {
    if (this.observer) {
      this.observer.disconnect();
      this.observer = undefined;
    }
  }
अंतिम कोड

यहां पूरा निर्देश है। यह सिर्फ एक अभ्यास था, इसलिए इसे अपनी पसंद के अनुसार बदलने के लिए स्वतंत्र रहें!


दृश्यता परिवर्तन टाइप करें = | { दृश्यमान: सत्य; लक्ष्य: HTMLElement; } | { दृश्यमान: असत्य; लक्ष्य: HTMLElement | अपरिभाषित; }; @निर्देश({ चयनकर्ता: "[दृश्यता]", स्टैंडअलोन: सच }) निर्यात वर्ग दृश्यता निर्देश OnChanges, OnInit, AfterViewInit, OnDestroy लागू करता है { निजी तत्व = इंजेक्ट(ElementRef); /** * दृश्य प्रारंभ होने के बाद उत्सर्जित होता है। */ निजी AfterViewInit$ = नया विषय(); /** * इस तत्व के लिए इंटरसेक्शनऑब्जर्वर। */ निजी पर्यवेक्षक: इंटरसेक्शनऑब्जर्वर | अपरिभाषित; /** * इस तत्व के लिए अंतिम ज्ञात दृश्यता। *शुरुआत में हमें पता नहीं चलता. */ निजी दृश्यमान है: बूलियन = अपरिभाषित; /** * यदि गलत है, तो एक बार तत्व दिखाई देने पर एक उत्सर्जन होगा और फिर कुछ भी नहीं। * यदि सत्य है, तो निर्देश लगातार तत्व को सुनता है और जब भी वह दिखाई देता है या दिखाई नहीं देता है तब उत्सर्जित करता है। */ दृश्यता मॉनिटर = इनपुट (झूठा); /** * तत्व दृश्यमान होने पर श्रोता को सूचित करता है। * यदि "विजिबिलिटी मॉनिटर" सत्य है, तो यह तत्व के दृश्य के अंदर/बाहर जाने पर श्रोता को लगातार सूचित करता है। */ दृश्यता परिवर्तन = आउटपुट(); ngOnInit(): शून्य { this.reconnectObserver(); } ngOnChanges(): शून्य { this.reconnectObserver(); } ngAfterViewInit(): शून्य { this.afterViewInit$.next(true); } ngOnDestroy(): शून्य { // डिस्कनेक्ट करें और यदि विजिबिलिटी मॉनिटर सही है, तो श्रोता को सूचित करें this.disconnectObserver(); यदि (यह दृश्यता मॉनिटर) { this.visibilityChange.emit({ दृश्यमान है: झूठा, लक्ष्य: अपरिभाषित }); } } निजी पुनः कनेक्टऑब्जर्वर(): शून्य { // मौजूदा पर्यवेक्षक को डिस्कनेक्ट करें this.disconnectObserver(); // एक नया पर्यवेक्षक स्थापित करता है this.observer = new IntersectionObserver((प्रविष्टियां, पर्यवेक्षक) => { प्रविष्टियाँ.प्रत्येक के लिए(प्रविष्टि => { स्थिरांक { isIntersecting: isVisible, target } = प्रविष्टि; const hasChangedVisibility = isVisible !== this.isVisible; स्थिरांक चाहिएएमिट = दृश्यमान है || (!दृश्यमान &&यह.दृश्यतामॉनिटर); यदि (दृश्यता बदल दी गई है और इसे उत्सर्जित करना चाहिए) { this.visibilityChange.emit({ दिखाई दे रहा है, लक्ष्य: HTMLElement के रूप में लक्ष्य करें }); यह दृश्यमान है = दृश्यमान है; } // यदि विज़िबिली मॉनिटर गलत है, तो तत्व दिखाई देने पर हम रुक जाते हैं। यदि (दृश्यमान है && !this.visibilityMonitor) { पर्यवेक्षक.डिस्कनेक्ट(); } }); }); // दृश्य प्रारंभ होने के बाद अवलोकन करना प्रारंभ करें this.afterViewInit$.subscribe(() => { this.observer?.observe(this.element.nativeElement); }); } निजी डिस्कनेक्टऑब्जर्वर(): शून्य { यदि (यह.पर्यवेक्षक) { this.observer.disconnect(); यह.पर्यवेक्षक = अपरिभाषित; } } }
type VisibilityChange =
  | {
      isVisible: true;
      target: HTMLElement;
    }
  | {
      isVisible: false;
      target: HTMLElement | undefined;
    };

@Directive({
  selector: "[visibility]",
  standalone: true
})
export class VisibilityDirective
  implements OnChanges, OnInit, AfterViewInit, OnDestroy {
  private element = inject(ElementRef);

  /**
   * Emits after the view is initialized.
   */
  private afterViewInit$ = new Subject();

  /**
   * The IntersectionObserver for this element.
   */
  private observer: IntersectionObserver | undefined;

  /**
   * Last known visibility for this element.
   * Initially, we don't know.
   */
  private isVisible: boolean = undefined;

  /**
   * If false, once the element becomes visible there will be one emission and then nothing.
   * If true, the directive continuously listens to the element and emits whenever it becomes visible or not visible.
   */
  visibilityMonitor = input(false);

  /**
   * Notifies the listener when the element has become visible.
   * If "visibilityMonitor" is true, it continuously notifies the listener when the element goes in/out of view.
   */
  visibilityChange = output();

  ngOnInit(): void {
    this.reconnectObserver();
  }

  ngOnChanges(): void {
    this.reconnectObserver();
  }

  ngAfterViewInit(): void {
    this.afterViewInit$.next(true);
  }

  ngOnDestroy(): void {
    // Disconnect and if visibilityMonitor is true, notify the listener
    this.disconnectObserver();
    if (this.visibilityMonitor) {
      this.visibilityChange.emit({
        isVisible: false,
        target: undefined
      });
    }
  }

  private reconnectObserver(): void {
    // Disconnect an existing observer
    this.disconnectObserver();
    // Sets up a new observer
    this.observer = new IntersectionObserver((entries, observer) => {
      entries.forEach(entry => {
        const { isIntersecting: isVisible, target } = entry;
        const hasChangedVisibility = isVisible !== this.isVisible;
        const shouldEmit = isVisible || (!isVisible && this.visibilityMonitor);
        if (hasChangedVisibility && shouldEmit) {
          this.visibilityChange.emit({
            isVisible,
            target: target as HTMLElement
          });
          this.isVisible = isVisible;
        }
        // If visilibilyMonitor is false, once the element is visible we stop.
        if (isVisible && !this.visibilityMonitor) {
          observer.disconnect();
        }
      });
    });
    // Start observing once the view is initialized
    this.afterViewInit$.subscribe(() => {
        this.observer?.observe(this.element.nativeElement);
    });
  }

  private disconnectObserver(): void {
    if (this.observer) {
      this.observer.disconnect();
      this.observer = undefined;
    }
  }
}
विज्ञप्ति वक्तव्य यह आलेख यहां पुन: प्रस्तुत किया गया है: https://dev.to/this-is-angular/angular-lab-let-create-a-visibility-directive-5dpp?1 यदि कोई उल्लंघन है, तो कृपया [email protected] पर संपर्क करें। इसे हटाने के लिए
नवीनतम ट्यूटोरियल अधिक>

चीनी भाषा का अध्ययन करें

अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।

Copyright© 2022 湘ICP备2022001581号-3