मैं $ गुंजाइश का उपयोग कैसे करूँ। $ घड़ी और $ गुंजाइश। $ AngularJS में लागू होते हैं?


1088

मुझे समझ नहीं आता उपयोग करने के लिए कैसे $scope.$watchऔर $scope.$apply। आधिकारिक दस्तावेज सहायक नहीं है।

मुझे विशेष रूप से समझ में नहीं आता है:

  • क्या वे DOM से जुड़े हैं?
  • मैं मॉडल में DOM परिवर्तन कैसे अपडेट कर सकता हूं?
  • उनके बीच संबंध बिंदु क्या है?

मैंने इस ट्यूटोरियल की कोशिश की , लेकिन यह समझ में आता है $watchऔर इसके $applyलिए दी गई है।

मैं क्या करूं $applyऔर $watchकैसे करूं, और मैं उनका उचित उपयोग कैसे करूं?

जवाबों:


1737

आपको यह समझने की आवश्यकता है कि इसे समझने के लिए AngularJS कैसे काम करता है।

पाचन चक्र और $ गुंजाइश

सबसे पहले और सबसे महत्वपूर्ण, AngularJS एक तथाकथित पाचन चक्र की अवधारणा को परिभाषित करता है । इस चक्र को एक लूप माना जा सकता है, जिसके दौरान AngularJS यह जांचता है कि क्या सभी चरों द्वारा देखे गए सभी चरों में कोई बदलाव है $scope। इसलिए यदि आपने $scope.myVarअपने नियंत्रक में परिभाषित किया है और इस चर को देखे जाने के लिए चिह्नित किया गया है , तो आप स्पष्ट रूप से AngularJS को इन परिवर्तनों की निगरानी के लिए बता रहे हैंmyVar लूप के प्रत्येक पुनरावृत्ति में ।

एक स्वाभाविक अनुवर्ती प्रश्न होगा: क्या सब कुछ $scopeदेखा जा रहा है से जुड़ा हुआ है ? सौभाग्य से, नहीं। यदि आप अपने में हर वस्तु में बदलाव के लिए देखते हैं $scope, तो जल्दी से एक पचाने वाले लूप का मूल्यांकन करने में उम्र लग जाएगी और आप जल्दी से प्रदर्शन के मुद्दों में भाग लेंगे। यही कारण है कि एंगुलरजेएस टीम ने हमें कुछ $scopeचर घोषित करने के दो तरीके बताए हैं, जिन्हें देखा जा रहा है (नीचे पढ़ें)।

$ घड़ी $ गुंजाइश परिवर्तनों के लिए सुनने में मदद करती है

एक $scopeचर को देखने के रूप में घोषित करने के दो तरीके हैं ।

  1. अभिव्यक्ति के माध्यम से अपने टेम्पलेट में इसका उपयोग करके <span>{{myVar}}</span>
  2. $watchसेवा के माध्यम से इसे मैन्युअल रूप से जोड़कर

विज्ञापन 1) यह सबसे आम परिदृश्य है और मुझे यकीन है कि आपने इसे पहले भी देखा है, लेकिन आप नहीं जानते कि इसने पृष्ठभूमि में एक घड़ी बनाई है। हाँ, यह था! AngularJS निर्देशों का उपयोग करना (जैसे किng-repeat ) भी निहित घड़ियों का निर्माण कर सकता है।

विज्ञापन 2) यह आप अपनी खुद की घड़ियों का निर्माण करते हैं । $watchसेवा आपको कुछ कोड चलाने में मदद करती है जब कुछ मूल्य $scopeबदले गए हैं। यह शायद ही कभी इस्तेमाल किया जाता है, लेकिन कभी-कभी मददगार होता है। उदाहरण के लिए, यदि आप प्रत्येक बार 'myVar' परिवर्तन के लिए कुछ कोड चलाना चाहते हैं, तो आप निम्न कार्य कर सकते हैं:

function MyController($scope) {

    $scope.myVar = 1;

    $scope.$watch('myVar', function() {
        alert('hey, myVar has changed!');
    });

    $scope.buttonClicked = function() {
        $scope.myVar = 2; // This will trigger $watch expression to kick in
    };
}

$ लागू डाइजेस्ट चक्र के साथ परिवर्तनों को एकीकृत करने में सक्षम बनाता है

आप $applyफ़ंक्शन को एक एकीकरण तंत्र के रूप में सोच सकते हैं । आप देखते हैं, हर बार जब आप कुछ देखे गए चर को बदलते हैं$scope सीधे वस्तु हैं, तो AngularJS को पता चलेगा कि परिवर्तन हो चुका है। ऐसा इसलिए है क्योंकि AngularJS पहले से ही उन परिवर्तनों की निगरानी करना जानता था। इसलिए यदि यह फ्रेमवर्क द्वारा प्रबंधित कोड में होता है, तो पाचन चक्र आगे बढ़ेगा।

हालाँकि, कभी-कभी आप AngularJS की दुनिया के बाहर कुछ मूल्य बदलना चाहते हैं और सामान्य रूप से परिवर्तन को देखते हैं। इस पर विचार करें - आपके पास एक $scope.myVarमूल्य है जिसे एक jQuery के $.ajax()हैंडलर के भीतर संशोधित किया जाएगा । यह भविष्य में किसी बिंदु पर होगा। AngularJS ऐसा होने के लिए इंतजार नहीं कर सकता, क्योंकि इसे jQuery पर प्रतीक्षा करने का निर्देश नहीं दिया गया है।

इससे निपटने के लिए, $apply पेश किया गया है। यह आपको पाचन चक्र को स्पष्ट रूप से शुरू करने देता है। हालाँकि, आपको इसका उपयोग केवल कुछ डेटा को AngularJS (अन्य फ्रेमवर्क के साथ एकीकरण) में माइग्रेट करने के लिए करना चाहिए, लेकिन नियमित AngularJS कोड के साथ संयुक्त इस पद्धति का उपयोग कभी न करें, क्योंकि AngularJS तब एक त्रुटि करेगा।

यह सब डोम से कैसे संबंधित है?

ठीक है, आपको वास्तव में ट्यूटोरियल को फिर से पालन करना चाहिए, अब जब आप यह सब जानते हैं। पाचन चक्र सुनिश्चित करेगा कि यूआई और जावास्क्रिप्ट कोड सभी के साथ जुड़े हुए प्रत्येक द्रष्टा का मूल्यांकन करके तब तक सिंक्रनाइज़ रहें, $scopeजब तक कुछ भी नहीं बदलता। अगर डाइजेस्ट लूप में अधिक बदलाव नहीं होते हैं, तो इसे समाप्त माना जाता है।

आप ऑब्जेक्ट को $scopeऑब्जेक्ट को या तो स्पष्ट रूप से कंट्रोलर में संलग्न कर सकते हैं , या उन्हें {{expression}}सीधे दृश्य में रूप में घोषित कर सकते हैं।

मुझे उम्मीद है कि इस सब के बारे में कुछ बुनियादी ज्ञान को स्पष्ट करने में मदद करता है।

आगे की रीडिंग:


57
"कोणीय जाँच करता है कि क्या सभी $ scopes से जुड़े सभी चर में कोई बदलाव है" - मुझे नहीं लगता कि यह काफी सही है। मेरा मानना ​​है कि एंगुलर केवल (गंदे) $ स्कोप गुणों की जाँच करता है जिनकी $ घड़ियाँ सेट की गई हैं (ध्यान दें कि {{}} का उपयोग किसी दृश्य में स्वचालित रूप से एक घड़ी बनाएगी)। स्कोप पृष्ठ पर "स्कोप $ वॉच प्रदर्शन विचार" अनुभाग भी देखें ।
मार्क राजकॉक

5
यह मामला हो सकता है। मैं इसके बारे में अधिक पढ़ने और अपने उत्तर को संपादित करने के लिए कुछ समय खोजने की कोशिश करूँगा।
atukaszBachman

15
@ मर्कराजकोक, आप सही थे। मैंने अपना उत्तर बदल दिया और एक लेख की ओर संकेत किया जो अच्छी तरह से दिखाता है कि यह कैसे लागू किया जाता है।
atउकसज़बाचमैन

3
इसका उपयोग करने के बारे में क्या? ("नियंत्रण के रूप में" विधि)
Leandro

2
"नियंत्रण के रूप में" का उपयोग करने से ऊपर की जानकारी पर कोई प्रभाव नहीं होना चाहिए। This.myVar का उपयोग करना myVar को दायरे में लाता है।
मार्कस रैडेल

161

AngularJS में, हम अपने मॉडल अपडेट करते हैं, और हमारे विचार / टेम्पलेट DOM को "स्वचालित रूप से" (अंतर्निहित या कस्टम निर्देशों के माध्यम से) अपडेट करते हैं।

$ लागू और $ घड़ी, दोनों स्कोप तरीके हैं, डोम से संबंधित नहीं हैं।

अवधारणाओं पेज (अनुभाग "क्रम") $ पचाने पाश की एक बहुत अच्छी व्याख्या, $ लागू होते हैं, $ evalAsync कतार और $ घड़ी सूची है। यहां वह चित्र है जो पाठ के साथ है:

$ पच लूप

जो भी कोड एक दायरे तक पहुंचता है - सामान्य रूप से नियंत्रक और निर्देश (उनके लिंक फ़ंक्शन और / या उनके नियंत्रक) - एक " watchExpression " सेट कर सकता है कि AngularJS उस दायरे के खिलाफ मूल्यांकन करेगा। यह मूल्यांकन तब होता है जब भी AngularJS अपने $ डाइजेस्ट लूप (विशेष रूप से, "$ वॉच लिस्ट" लूप) में प्रवेश करता है। आप अलग-अलग गुंजाइश गुण देख सकते हैं, आप दो गुणों को एक साथ देखने के लिए एक फ़ंक्शन को परिभाषित कर सकते हैं, आप एक सरणी की लंबाई देख सकते हैं, आदि।

जब चीजें "एंगुलरजेएस के अंदर" होती हैं - उदाहरण के लिए, आप एक टेक्स्टबॉक्स में टाइप करते हैं जिसमें एंगुलरजेएस टू-वे डेटाबाइंडिंग सक्षम है (यानी, एनजी-मॉडल का उपयोग करता है), एक $ http कॉलबैक आग, आदि - $ लागू पहले ही कहा जाता है, इसलिए हम कहते हैं ऊपर के चित्र में "AngularJS" आयत के अंदर। सभी watchExpressions का मूल्यांकन किया जाएगा (संभवतः एक से अधिक बार - जब तक कि कोई और परिवर्तन का पता न चले)।

जब चीजें "एंगुलरजेएस के बाहर" होती हैं - उदाहरण के लिए, आपने एक निर्देश में बाइंड () का उपयोग किया और फिर उस घटना में आग लग जाती है, जिसके परिणामस्वरूप आपके कॉलबैक को कॉल किया जाता है, या कुछ jQuery के पंजीकृत कॉलबैक फायर होते हैं - हम अभी भी "मूल" आयत में हैं। यदि कॉलबैक कोड कुछ भी संशोधित करता है जो कोई भी $ वॉच देख रहा है, तो $ $ को AngularJS आयत में लाने के लिए कॉल करें, जिससे $ डाइजेस्ट लूप चले, और इसलिए AngularJS परिवर्तन को नोटिस करेगा और उसका जादू करेगा।


5
मैं इस विचार को समझता हूं, जो मुझे समझ में नहीं आता है कि डेटा वास्तव में कैसे स्थानांतरित हो जाता है। मेरे पास एक मॉडल है जो बहुत सारे डेटा के साथ एक ऑब्जेक्ट है, मैं इसका उपयोग डोम में हेरफेर करने के लिए करता हूं। फिर इसमें से कुछ बदल जाता है। मैं बदले हुए डेटा को मॉडल में सही जगह पर कैसे रखूँ? मैंने जिस उदाहरण का उपयोग किया, वह हेरफेर करता है और अंत में बस उपयोग करता है scope.$apply(scope.model), मुझे समझ में नहीं आता है कि क्या डेटा स्थानांतरित हो जाता है और इसे मॉडल में सही जगह पर कैसे स्थानांतरित किया जाता है?
ilo

6
कोई जादुई डेटा ट्रांसफर नहीं हो रहा है। सामान्य रूप से कोणीय एप्लिकेशन के साथ, आपको कोणीय मॉडल को बदलना चाहिए, जो तब व्यू / डोम अपडेट को ड्राइव करता है। यदि आप कोणीय के बाहर DOM को अपडेट करते हैं, तो आपको मैन्युअल रूप से मॉडल्स को अपडेट करना होगा। scope.$apply(scope.model)बस scope.modelएक कोणीय अभिव्यक्ति के रूप में मूल्यांकन करेगा , और फिर एक $ पच पाश दर्ज करें। आपके द्वारा संदर्भित लेख में, संभवतः scope.$apply()पर्याप्त होगा, क्योंकि मॉडल पहले से ही $ watch'ed है। स्टॉप () फ़ंक्शन मॉडल को अपडेट कर रहा है (मेरा मानना ​​है कि टुपडेट स्कोप स्कोटलोड के लिए एक संदर्भ है), और फिर $ एप को बुलाया जाता है।
मार्क राजकॉक

ऐसा लगता है कि इस उत्तर के तहत एंगुलरजेएस डॉक्स हट गए हैं (पहला लिंक "रनटाइम" या $watchपेज पर नहीं है , और दूसरा लिंक टूट गया है - अब तक, किसी भी तरह)। दर्दनाक रूप से, संग्रह संस्करणों ने कैश नहीं किया जो कुछ भी async प्रक्रिया ने सामग्री बनाई।
रफिन

52

AngularJS इस इवेंट-लूप को बढ़ाता है , जिसे कुछ कहा जाता है AngularJS context

घड़ी $ ()

हर बार जब आप यूआई में किसी चीज को बांधते हैं तो आप $watchएक $watchसूची में सम्मिलित होते हैं ।

User: <input type="text" ng-model="user" />
Password: <input type="password" ng-model="pass" />

हमारे पास है $scope.user , जो पहले इनपुट के लिए बाध्य है, और हमारे पास है $scope.pass, जो दूसरे के लिए बाध्य है। ऐसा करते हुए हम सूची में दो $watchतों$watch जोड़ते हैं ।

जब हमारे टेम्प्लेट को लोड किया जाता है, लिंकिंग चरण में AKA, कंपाइलर प्रत्येक निर्देश को देखेगा और सभी $watchआवश्यक बनाता है ।

AngularJS प्रदान करता है $watch, $watchcollectionऔर $watch(true)। नीचे एक साफ आरेख है जो सभी तीनों को गहराई से देखने वालों से लिया गया है

यहां छवि विवरण दर्ज करें

angular.module('MY_APP', []).controller('MyCtrl', MyCtrl)
function MyCtrl($scope,$timeout) {
  $scope.users = [{"name": "vinoth"},{"name":"yusuf"},{"name":"rajini"}];

  $scope.$watch("users", function() {
    console.log("**** reference checkers $watch ****")
  });

  $scope.$watchCollection("users", function() {
    console.log("**** Collection  checkers $watchCollection ****")
  });

  $scope.$watch("users", function() {
    console.log("**** equality checkers with $watch(true) ****")
  }, true);

  $timeout(function(){
     console.log("Triggers All ")
     $scope.users = [];
     $scope.$digest();

     console.log("Triggers $watchCollection and $watch(true)")
     $scope.users.push({ name: 'Thalaivar'});
     $scope.$digest();

     console.log("Triggers $watch(true)")
     $scope.users[0].name = 'Superstar';
     $scope.$digest();
  });
}

http://jsfiddle.net/2Lyn0Lkb/

$digest पाश

जब ब्राउज़र को एक घटना मिलती है जिसे AngularJS संदर्भ द्वारा प्रबंधित किया जा सकता है तो $digestलूप को निकाल दिया जाएगा। यह लूप दो छोटे छोरों से बनाया गया है। एक $evalAsyncकतार की प्रक्रिया करता है , और दूसरा प्रक्रिया करता है $watch list$digestकी सूची के माध्यम इच्छा पाश $watchहै कि हम

app.controller('MainCtrl', function() {
  $scope.name = "vinoth";

  $scope.changeFoo = function() {
      $scope.name = "Thalaivar";
  }
});

{{ name }}
<button ng-click="changeFoo()">Change the name</button>

यहां हमारे पास केवल एक ही है $watchक्योंकि एनजी-क्लिक किसी भी घड़ियों का निर्माण नहीं करता है।

हम बटन दबाते हैं।

  1. ब्राउज़र को एक घटना मिलती है जो AngularJS संदर्भ में प्रवेश करेगी
  2. $digestपाश चलेंगे और परिवर्तन के लिए हर $ घड़ी के लिए कहेगा।
  3. चूँकि $watchजो $ स्कोप में बदलाव के लिए देख रहा था। एक बदलाव की रिपोर्ट करता है, यह दूसरे को मजबूर करेगा$digest लूप ।
  4. नया लूप कुछ नहीं की रिपोर्ट करता है।
  5. ब्राउज़र को नियंत्रण वापस मिल जाता है और यह DOM को $ गुंजाइश के नए मूल्य को दर्शाता है
  6. यहां महत्वपूर्ण बात यह है कि एंगुलरजेएस संदर्भ में प्रवेश करने वाली हर घटना एक $digestलूप चलेगी । इसका मतलब है कि हर बार जब हम एक इनपुट में एक पत्र लिखते हैं, तो लूप $watchइस पृष्ठ में हर चेकिंग को चलाएगा ।

$ लागू ()

यदि आप $applyकिसी घटना के निकाल दिए जाने पर कॉल करते हैं, तो यह कोणीय-संदर्भ के माध्यम से जाएगा, लेकिन यदि आप इसे कॉल नहीं करते हैं, तो यह इसके बाहर चलेगा। यह बेहद आसान है। आंतरिक रूप $applyसे$digest() लूप को बुलाएगा और यह सुनिश्चित करने के लिए सभी घड़ियों पर पुनरावृत्ति करेगा कि डोम को नए अद्यतन मूल्य के साथ अपडेट किया गया है।

$apply()विधि पूरे पर नजर रखने वालों को गति प्रदान करेगा $scopeश्रृंखला जबकि $digest()विधि केवल वर्तमान पर नजर रखने वालों को गति प्रदान करेगा $scopeऔर उसके childrenजब $scopeस्थानीय परिवर्तनों के बारे में किसी भी उच्च-अप ऑब्जेक्ट को जानने की आवश्यकता नहीं है, तो आप उपयोग कर सकते हैं $digest()


18

मैं बहुत गहराई से वीडियो नहीं मिले जो कवर $watch, $apply, $digestऔर में चक्र को पचाने:

उन वीडियो में उन अवधारणाओं के बारे में बताने के लिए कुछ स्लाइड्स का उपयोग किया गया है (यदि केवल उपरोक्त लिंक हटा दिए गए हैं / काम नहीं कर रहे हैं)।

यहां छवि विवरण दर्ज करें

उपरोक्त छवि में, "$ गुंजाइश।" नहीं देखी जा रही है क्योंकि यह किसी भी डेटा बाइंडिंग (मार्किंग में) में उपयोग नहीं किया गया है। अन्य दो ( $scope.aऔर $scope.b) देखे जाएंगे।

यहां छवि विवरण दर्ज करें

उपरोक्त छवि से: संबंधित ब्राउज़र इवेंट के आधार पर, AngularJS ईवेंट को कैप्चर करता है, डाइजेस्ट साइकल करता है (परिवर्तनों के लिए सभी घड़ियों के माध्यम से जाता है), वॉच फ़ंक्शंस निष्पादित करें और DOM को अपडेट करें। यदि ब्राउज़र ईवेंट नहीं हैं, तो पाचन चक्र का उपयोग करके मैन्युअल रूप से ट्रिगर किया जा सकता है $applyया $digest

के बारे में $applyऔर अधिक $digest:

यहां छवि विवरण दर्ज करें


17

कर रहे हैं $watchGroupऔर $watchCollectionसाथ ही। विशेष रूप से, $watchGroupवास्तव में उपयोगी है यदि आप किसी ऑब्जेक्ट को अपडेट करने के लिए फ़ंक्शन को कॉल करना चाहते हैं जिसमें एक दृश्य में कई गुण हैं जो डोम ऑब्जेक्ट नहीं है, उदाहरण के लिए कैनवास, वेबजीएल या सर्वर अनुरोध में एक और दृश्य ।

यहाँ, प्रलेखन लिंक


मैंने टिप्पणी की होगी, $watchCollectionलेकिन मैं आपको पहले ही देख चुका हूं। यहाँ AngularJS साइट से इसके बारे में प्रलेखन है । वे $watchगहराई का एक बहुत अच्छा दृश्य प्रदान करते हैं । नोट सूचना पृष्ठ के नीचे के करीब है।
JabberwockyDecompiler

15

बस उपरोक्त सभी पढ़ना, उबाऊ और नींद पूरी करना (क्षमा करें लेकिन सच है)। बहुत ही तकनीकी, गहन, विस्तृत और शुष्क। मैं क्यों लिख रहा हूँ? क्योंकि AngularJS बड़े पैमाने पर है, बहुत सारे इंटर-कनेक्टेड कॉन्सेप्ट्स किसी को भी पागल कर सकते हैं। मैंने अक्सर खुद से पूछा, क्या मैं उन्हें समझने के लिए पर्याप्त स्मार्ट नहीं हूं? नहीं! ऐसा इसलिए है क्योंकि कुछ ही तकनीकी रूप से डमी भाषा w / o में सभी शब्दावली समझा सकते हैं ! ठीक है, मुझे कोशिश करें:

1) वे सभी घटना-संचालित चीजें हैं। (मैं हंसी सुनता हूं, लेकिन पढ़ता हूं)

यदि आपको नहीं पता है कि ईवेंट-चालित क्या है, तो सोचें कि आप पृष्ठ पर एक बटन रखते हैं, इसे "ऑन-क्लिक" का उपयोग करके w / एक फ़ंक्शन को हुक करें, उपयोगकर्ताओं द्वारा आपके द्वारा अंदर की जाने वाली क्रियाओं को ट्रिगर करने के लिए उस पर क्लिक करने की प्रतीक्षा करें। समारोह। या SQL सर्वर / Oracle के "ट्रिगर" के बारे में सोचें।

2) $ घड़ी "ऑन-क्लिक" है।

विशेष बात यह है कि पैरामीटर के रूप में यह 2 कार्य करता है, पहले एक घटना से मूल्य देता है, दूसरा एक मूल्य को ध्यान में रखता है ...

3) $ डाइजेस्ट वह बॉस है जो अथक , ब्ला-ब्ला-ब्ला लेकिन एक अच्छा बॉस है।

4) $ लागू करने से आपको वह तरीका मिलता है जब आप इसे मैन्युअल रूप से करना चाहते हैं , जैसे कि एक विफल-प्रूफ (अगर क्लिक में किक नहीं होती है, तो आप इसे चलाने के लिए बाध्य करते हैं।)

अब, इसे दृश्य बनाते हैं। इस तस्वीर को विचार को हथियाने के लिए और भी आसान बनाने के लिए इसे देखें:

एक भोजनालय में,

- WAITERS

ग्राहकों से ऑर्डर लेना चाहिए, यह है

$watch(
  function(){return orders;},
  function(){Kitchen make it;}
);

- यह सुनिश्चित करने के लिए कि सभी वेटर जाग रहे हैं, ग्राहकों से परिवर्तन के किसी भी संकेत के लिए उत्तरदायी हैं। ये है$digest()

- OWNER के पास अनुरोध करने पर सभी को चलाने की अंतिम शक्ति है$apply()


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