AngularJS $ घड़ी के बराबर कोणीय क्या है?


213

AngularJS में आप देखने वालों को $watchफ़ंक्शन के उपयोग से कार्यक्षेत्र चर में परिवर्तन देखने के लिए निर्दिष्ट करने में सक्षम थे $scope। कोणीय परिवर्तन (उदाहरण के लिए, घटक चर) में परिवर्तन के लिए देखने के बराबर क्या है?


टाइपस्क्रिप्ट में एक्सेसर का उपयोग करें।
जम्मूतवीरणादि

इस लेख की जाँच करें जो अंतर को स्पष्ट करता है
मैक्स कोरेत्स्की

जवाबों:


268

कोणीय 2 में, परिवर्तन का पता लगाना स्वचालित है ... $scope.$watch()और $scope.$digest()RIP

दुर्भाग्य से, देव गाइड के चेंज डिटेक्शन सेक्शन को अभी तक नहीं लिखा गया है ( "द अदर स्टफ" सेक्शन में आर्किटेक्चर ओवरव्यू पेज के नीचे एक प्लेसहोल्डर है )।

यह पता लगाने की मेरी समझ है कि परिवर्तन कैसे काम करता है:

  • जोन। जेएस "बंदर दुनिया को पैच करता है" - यह ब्राउज़र में सभी अतुल्यकालिक एपीआई (जब कोणीय) होता है। यही कारण है कि हम setTimeout()अपने घटकों के अंदर का उपयोग कर सकते हैं जैसे $timeoutकि कुछ ... क्योंकि setTimeout()बंदर पैच है।
  • कोणीय "परिवर्तन डिटेक्टरों" के एक पेड़ का निर्माण और रखरखाव करता है। प्रति घटक / निर्देश प्रति एक ऐसा परिवर्तन डिटेक्टर (वर्ग) है। (आप इंजेक्शन द्वारा इस वस्तु तक पहुंच प्राप्त कर सकते हैं ChangeDetectorRef।) ये परिवर्तन डिटेक्टर तब बनाए जाते हैं जब कोणीय घटक बनाते हैं। वे गंदे चेकिंग के लिए आपकी सभी बाइंडिंग की स्थिति पर नज़र रखते हैं। ये एक अर्थ में, ऑटोमैटिक के समान हैं $watches()जो कोणीय 1 {{}}टेम्पलेट बाइंडिंग के लिए स्थापित होंगे ।
    कोणीय 1 के विपरीत, परिवर्तन का पता लगाने का ग्राफ एक निर्देशित पेड़ है और इसमें चक्र नहीं हो सकते हैं (यह कोणीय 2 बहुत अधिक प्रदर्शन करता है, जैसा कि हम नीचे देखेंगे)।
  • जब कोई घटना (कोणीय क्षेत्र के अंदर) फायर करती है, तो हमने जो कोड लिखा था (ईवेंट हैंडलर कॉलबैक) चलता है। यह जो भी डेटा चाहता है उसे अपडेट कर सकता है - साझा किए गए एप्लिकेशन मॉडल / राज्य और / या घटक के दृश्य स्थिति।
  • उसके बाद, हुक के क्षेत्र के कारण। Js जोड़ा गया, यह तब कोणीय परिवर्तन खोज एल्गोरिथ्म चलाता है। डिफ़ॉल्ट रूप से (यानी, यदि आप onPushअपने किसी भी घटक पर परिवर्तन का पता लगाने की रणनीति का उपयोग नहीं कर रहे हैं ), तो पेड़ के हर घटक की एक बार (TTL = 1) ... गहराई से, पहले क्रम में जांच की जाती है। (ठीक है, यदि आप देव मोड में हैं, तो परिवर्तन का पता लगाने दो बार (TTL = 2) चलता है। ApplicationRef.tick () इस बारे में अधिक जानकारी के लिए देखें ।) यह उन सभी डिटेक्टरों का उपयोग करके आपके सभी बाइंडिंग पर गंदी जाँच करता है।
    • जीवनचक्र के हुक को परिवर्तन का पता लगाने के भाग के रूप में कहा जाता है।
      यदि आप जिस घटक डेटा को देखना चाहते हैं वह एक आदिम इनपुट संपत्ति (स्ट्रिंग, बूलियन, संख्या) है, तो आप ngOnChanges()परिवर्तनों के बारे में सूचित किए जाने के लिए कार्यान्वित कर सकते हैं।
      यदि इनपुट संपत्ति एक संदर्भ प्रकार (ऑब्जेक्ट, एरे, आदि) है, लेकिन संदर्भ नहीं बदला (उदाहरण के लिए, आपने किसी आइटम को मौजूदा सरणी में जोड़ा है), तो आपको इसे लागू करना होगा ngDoCheck()( इस SO उत्तर को और देखें) इस पर)।
      आपको केवल घटक के गुणों और / या वंशज घटकों के गुणों को बदलना चाहिए (क्योंकि एकल ट्री वॉक कार्यान्वयन - यानी, यूनिडायरेक्शनल डेटा फ्लो)। यहाँ एक प्लंकर है जो इसका उल्लंघन करता है। स्टेटफुल पाइप भी आपको यहां तक पहुंचा सकते हैं।
  • जो भी बाइंडिंग परिवर्तन पाए जाते हैं, उनके लिए घटक अपडेट किए जाते हैं, और फिर DOM अपडेट किया जाता है। परिवर्तन का पता लगाना अब समाप्त हो गया है।
  • ब्राउज़र डोम परिवर्तन और स्क्रीन को अपडेट करता है।

अधिक जानने के लिए अन्य संदर्भ:


window.addEventListener () वेरिएबल बदलने पर डिटेक्शन ट्रिगर नहीं करता है ... यह मुझे पागल कर देता है, उस पर कहीं भी कुछ भी नहीं है।
अल्बर्ट जेम्स टेडी

@AlbertJamesTeddy, DirectVMetadata API डॉकhost में "होस्ट श्रोताओं" के दस्तावेज़ देखें । यह बताता है कि कोणीय क्षेत्र के अंदर से वैश्विक घटनाओं को कैसे सुनना है (इसलिए वांछित के रूप में परिवर्तन का पता लगाया जाएगा)। इस उत्तर में एक काम करने वाला प्लंकर है।
मार्क राजकोक

यह लिंक मददगार होगा ..
रिफ्लेक्टर

@ मर्कराजकोक, मैंने परिवर्तन खोज पर अपने लेख के संदर्भ को जोड़ने की स्वतंत्रता ली। आशा है कि आप बुरा नहीं मानेंगे यह महान विवरण में बताता है कि हुड के नीचे क्या होता है।
मैक्स Koretskyi

उस प्लंकर के बारे में, जो यूनिडायरेक्शनल डेटा फ्लो नियम का उल्लंघन करता है, मैं यह जोड़ना चाहूंगा कि अगर आप प्लंकर को EnableProdMode () के साथ चलाते हैं, तो आपको पैरेंट व्यू में कोई अपडेट नहीं दिखेगा, क्योंकि परिवर्तन डिटेक्टर एक बार चलता है।
मिस्टर .3

93

यह व्यवहार अब घटक जीवन चक्र का हिस्सा है।

एक घटक इनपुट परिवर्तनों की पहुँच प्राप्त करने के लिए OnChanges इंटरफ़ेस में ngOnChanges पद्धति को लागू कर सकता है ।

उदाहरण:

import {Component, Input, OnChanges} from 'angular2/core';


@Component({
  selector: 'hero-comp',
  templateUrl: 'app/components/hero-comp/hero-comp.html',
  styleUrls: ['app/components/hero-comp/hero-comp.css'],
  providers: [],
  directives: [],

  pipes: [],
  inputs:['hero', 'real']
})
export class HeroComp implements OnChanges{
  @Input() hero:Hero;
  @Input() real:string;
  constructor() {
  }
  ngOnChanges(changes) {
      console.log(changes);
  }
}

77
यह केवल @Input () के लिए सही है। यदि आप अपने घटक के अपने डेटा के परिवर्तनों को ट्रैक करना चाहते हैं, तो यह काम नहीं करेगा
LanderV

4
मुझे साधारण चर (उदाहरण के लिए बूलियन) के परिवर्तन नहीं मिले। केवल वस्तुओं के परिवर्तन का पता लगाया जाता है।
मटोलू

घटक के डेकोरेटर में "इनपुट" सरणी जोड़ने की आवश्यकता क्यों है? परिवर्तन का पता लगाने के बिना यह भी काम करेगा।
गिल एप्सटेन

68

यदि, स्वचालित दो-तरफ़ा बाइंडिंग के अलावा, आप किसी फ़ंक्शन को कॉल करना चाहते हैं जब कोई मान बदलता है, तो आप दो-तरफ़ा बाइंडिंग शॉर्टकट सिंटैक्स को अधिक वर्बोज़ संस्करण में तोड़ सकते हैं।

<input [(ngModel)]="yourVar"></input>

के लिए आशुलिपि है

<input [ngModel]="yourVar" (ngModelChange)="yourVar=$event"></input>

(उदाहरण देखें http://victorsavkin.com/post/119943127151/angular-2-template-satstat )

आप ऐसा कुछ कर सकते हैं:

<input [(ngModel)]="yourVar" (ngModelChange)="changedExtraHandler($event)"></input>


पिछले उदाहरण में आप को हटाने का मतलब था [] ngModel के आसपास?
यूजीन कुलबुहोव

16

आप कोणीय 2 पर घड़ी के रूप में उपयोग getter functionया get accessorकार्य कर सकते हैं ।

डेमो देखें यहाँ

import {Component} from 'angular2/core';

@Component({
  // Declare the tag name in index.html to where the component attaches
  selector: 'hello-world',

  // Location of the template for this component
  template: `
  <button (click)="OnPushArray1()">Push 1</button>
  <div>
    I'm array 1 {{ array1 | json }}
  </div>
  <button (click)="OnPushArray2()">Push 2</button>
  <div>
    I'm array 2 {{ array2 | json }}
  </div>
  I'm concatenated {{ concatenatedArray | json }}
  <div>
    I'm length of two arrays {{ arrayLength | json }}
  </div>`
})
export class HelloWorld {
    array1: any[] = [];
    array2: any[] = [];

    get concatenatedArray(): any[] {
      return this.array1.concat(this.array2);
    }

    get arrayLength(): number {
      return this.concatenatedArray.length;
    }

    OnPushArray1() {
        this.array1.push(this.array1.length);
    }

    OnPushArray2() {
        this.array2.push(this.array2.length);
    }
}

12

यहां मॉडल के लिए गेट्टर और सेटर फ़ंक्शन का उपयोग करने का एक और तरीका है।

@Component({
  selector: 'input-language',
  template: `
  …
  <input 
    type="text" 
    placeholder="Language" 
    [(ngModel)]="query" 
  />
  `,
})
export class InputLanguageComponent {

  set query(value) {
    this._query = value;
    console.log('query set to :', value)
  }

  get query() {
    return this._query;
  }
}

4
यह विषय पागल है। मेरे पास एक जटिल रूप से बंधे कई गुणों के साथ एक वस्तु है । मैं (change)उनमें से हर एक पर हैंडलर (ओं) को जोड़ना नहीं चाहता ; मैं get|setsअपने मॉडल में प्रत्येक संपत्ति में s जोड़ना नहीं चाहता ; यह एक जोड़ने के get|setलिए मदद नहीं करेगा this.object; ngOnChanges() केवल @Inputएस में परिवर्तन का पता लगाता है । पवित्र मन्ना! उन्होंने हमारा क्या किया ??? हमें किसी तरह की गहरी घड़ी वापस दें!
कोडी

6

यदि आप इसे 2 तरह से बाध्यकारी बनाना चाहते हैं, तो आप उपयोग कर सकते हैं [(yourVar)], लेकिन आपको yourVarChangeईवेंट को कार्यान्वित करना होगा और इसे हर बार आपके परिवर्तनशील परिवर्तन को कॉल करना होगा।

नायक परिवर्तन को ट्रैक करने के लिए कुछ इस तरह

@Output() heroChange = new EventEmitter();

और फिर जब आपका हीरो बदल जाए, तो कॉल करें this.heroChange.emit(this.hero);

[(hero)]आप के लिए आराम करेंगे बाध्यकारी

यहाँ उदाहरण देखें:

http://plnkr.co/edit/efOGIJ0POh1XQeRZctSx?p=preview



2

यह सीधे प्रश्न का उत्तर नहीं देता है, लेकिन मैं कुछ अलग-अलग अवसरों पर इस स्टैक ओवरफ्लो प्रश्न पर उतरा हूं ताकि कुछ को हल करने के लिए मैं कोणीयज में $ घड़ी का उपयोग कर सकूं। मैंने वर्तमान उत्तरों में वर्णित की तुलना में एक और दृष्टिकोण का उपयोग करके समाप्त कर दिया है, और यदि कोई इसे उपयोगी पाता है तो मैं इसे साझा करना चाहता हूं।

जिस तकनीक का मैं कुछ समान हासिल करने के लिए उपयोग करता हूं $watchवह है BehaviorSubject( एक विषय पर अधिक ) यहां एक कोणीय सेवा में उपयोग करना, और परिवर्तनों को प्राप्त करने (देखने) के लिए मेरे घटकों को इसकी सदस्यता लेने दें। यह $watchकोणीयजे में एक के समान है , लेकिन इसके लिए कुछ और सेटअप और समझ की आवश्यकता होती है।

मेरे घटक में:

export class HelloComponent {
  name: string;
  // inject our service, which holds the object we want to watch.
  constructor(private helloService: HelloService){
    // Here I am "watching" for changes by subscribing
    this.helloService.getGreeting().subscribe( greeting => {
      this.name = greeting.value;
    });
  }
}

मेरी सेवा में

export class HelloService {
  private helloSubject = new BehaviorSubject<{value: string}>({value: 'hello'});
  constructor(){}
  // similar to using $watch, in order to get updates of our object 
  getGreeting(): Observable<{value:string}> {
    return this.helloSubject;
  }
  // Each time this method is called, each subscriber will receive the updated greeting.
  setGreeting(greeting: string) {
    this.helloSubject.next({value: greeting});
  }
}

यहाँ Stackblitz पर एक डेमो है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.