AngularJS में डेटा बाइंडिंग कैसे काम करती है?


1956

AngularJSफ्रेमवर्क में डेटा बाइंडिंग कैसे काम करती है?

मुझे उनकी साइट पर तकनीकी विवरण नहीं मिला है । यह अधिक या कम स्पष्ट है कि यह कैसे काम करता है जब डेटा को मॉडल से मॉडल तक प्रचारित किया जाता है। लेकिन AngularJS कैसे बसने वालों और गेटर्स के बिना मॉडल प्रॉपर्टीज के बदलावों को ट्रैक करता है?

मैंने पाया कि जावास्क्रिप्ट पर नजर रखने वाले हैं जो यह काम कर सकते हैं। लेकिन वे इंटरनेट एक्सप्लोरर 6 और इंटरनेट एक्सप्लोरर 7 में समर्थित नहीं हैं । तो AngularJS कैसे जानता है कि मैंने उदाहरण के लिए निम्नलिखित को बदल दिया है और इस परिवर्तन को एक दृश्य पर प्रतिबिंबित किया है?

myobject.myproperty="new value";

10
ध्यान रखें कि कोणीय 1.0.0rc1 के बाद से आपको अपने मामूली अद्यतन को अपडेट करने के लिए एनजी-मॉडल-इंस्टेंट ( डॉक्स-next.angularjs.org/api/… ) निर्दिष्ट करना होगा । अन्यथा इसे ब्लर ईवेंट पर अपडेट किया जाएगा।
सोतोमजोर

8
मार्सेलो का लिंक स्पष्ट रूप से टूटा हुआ है, इसलिए यहां यह फिर से है: github.com/mhevery/angular.js/blob/master/docs/content/guide/…
riffraff

6
@orian, वह लिंक खराब है। अपडेट किया गया (मुझे लगता है) वही है - docs.angularjs.org/guide/databinding
केविन मेरेडिथ

11
इस प्रश्न को पढ़ने वाले लोगों के लिए, कृपया ध्यान दें कि वेब घटकों के साथ काम करने और नीचे दिए गए उत्तरों में बहुत सारे मुद्दों को हल करने के लिए कोणीय 1.x के बाद से Angular 2.0 में भारी बदलाव आया है।
अगस्‍त

जवाबों:


2744

AngularJS मूल्य को याद रखता है और पिछले मूल्य से तुलना करता है। यह बुनियादी गंदी-जाँच है। यदि मूल्य में कोई परिवर्तन होता है, तो यह परिवर्तन घटना को आग लगा देता है।

$apply()विधि है, जो है कि तुम क्या कहते हैं जब आप एक AngularJS दुनिया में एक गैर AngularJS दुनिया से परिवर्तित कर रहे हैं, कॉल $digest()। एक पाचन सिर्फ सादा पुराना गंदा-जाँच है। यह सभी ब्राउज़रों पर काम करता है और पूरी तरह से अनुमानित है।

गंदी-जाँच (AngularJS) बनाम श्रोताओं ( नॉकआउटJS और Backbone.js ) को विपरीत करने के लिए : जबकि गंदी जाँच सरल लग सकती है, और यहां तक ​​कि अक्षम (मैं बाद में संबोधित करूँगा), यह पता चलता है कि यह शब्दार्थ सभी समय सही है। जबकि श्रोताओं के पास अजीब कोने के बहुत सारे मामले हैं और इसे अधिक शब्दार्थी बनाने के लिए निर्भरता ट्रैकिंग जैसी चीजों की आवश्यकता है। नॉकआउटजेएस निर्भरता ट्रैकिंग एक समस्या के लिए एक चतुर विशेषता है जो एंगुलरजेएस के पास नहीं है।

परिवर्तन श्रोताओं के साथ मुद्दे:

  • सिंटैक्स अत्याचारी है, क्योंकि ब्राउज़र इसे मूल रूप से समर्थन नहीं करते हैं। हाँ, वहाँ परदे के पीछे हैं, लेकिन वे सभी मामलों में शब्दार्थ से सही नहीं हैं, और निश्चित रूप से पुराने ब्राउज़र पर कोई परदे के पीछे नहीं हैं। लब्बोलुआब यह है कि गंदी-जांच आपको POJO करने की अनुमति देती है , जबकि नॉकआउट जेएस और बैकबोन.जेएस आपको उनकी कक्षाओं से विरासत में प्राप्त करने के लिए मजबूर करते हैं, और एक्सेसरों के माध्यम से आपके डेटा तक पहुंच बनाते हैं।
  • सहिष्णुता बदलें। मान लीजिए कि आपके पास मदों की एक सरणी है। कहते हैं कि आप किसी सरणी में आइटम जोड़ना चाहते हैं, जैसा कि आप जोड़ने के लिए लूप कर रहे हैं, हर बार जब आप जोड़ते हैं, तो आप बदलाव पर घटनाओं को निकाल रहे हैं, जो यूआई प्रदान कर रहा है। प्रदर्शन के लिए यह बहुत बुरा है। आप जो चाहते हैं वह अंत में केवल एक बार यूआई को अपडेट करना है। परिवर्तन की घटनाएं बहुत बारीक हैं।
  • चेंजर्स श्रोताओं को एक सेटर पर तुरंत आग लगा देते हैं, जो एक समस्या है, क्योंकि परिवर्तन श्रोता डेटा को और बदल सकता है, जो अधिक परिवर्तन की घटनाओं को भड़काता है। यह तब से खराब है जब आपके स्टैक पर आपको एक साथ कई बदलाव की घटनाएं हो सकती हैं। मान लीजिए कि आपके पास दो सरणियाँ हैं जिन्हें किसी भी कारण से सिंक में रखने की आवश्यकता है। आप केवल एक या दूसरे को जोड़ सकते हैं, लेकिन हर बार जब आप जोड़ते हैं तो एक परिवर्तन की घटना होती है, जिसमें अब दुनिया का एक असंगत दृश्य है। यह थ्रेड लॉकिंग की एक समान समस्या है, जिसे विशेष रूप से और पूरा होने के बाद से प्रत्येक कॉलबैक निष्पादित होने से जावास्क्रिप्ट बचता है। परिवर्तन की घटनाओं ने इसे तोड़ दिया क्योंकि बसने के दूरगामी परिणाम हो सकते हैं जो कि अभीष्ट और गैर-स्पष्ट नहीं हैं, जो कि थ्रेड समस्या को फिर से पैदा करता है। यह पता चला है कि आप जो करना चाहते हैं वह श्रोता निष्पादन में देरी करना है, और गारंटी देता है,

प्रदर्शन के बारे में क्या?

तो ऐसा लग सकता है कि हम धीमे हैं, क्योंकि गंदी-जाँच अक्षम है। यह वह जगह है जहां हमें केवल सैद्धांतिक तर्कों के बजाय वास्तविक संख्याओं को देखने की आवश्यकता है, लेकिन पहले कुछ बाधाओं को परिभाषित करें।

मनुष्य हैं:

  • धीमा - 50 एमएस से अधिक तेज कुछ भी मनुष्यों के लिए अस्वीकार्य है और इस प्रकार इसे "तत्काल" माना जा सकता है।

  • सीमित - आप वास्तव में एक पृष्ठ पर मानव को लगभग 2000 से अधिक जानकारी नहीं दिखा सकते हैं। इससे अधिक कुछ भी वास्तव में बुरा यूआई है, और मानव वैसे भी इसे संसाधित नहीं कर सकता है।

तो असली सवाल यह है: आप 50 एमएस में एक ब्राउज़र पर कितनी तुलना कर सकते हैं? यह एक कठिन सवाल है जिसका जवाब देने के लिए कई कारक खेल में आते हैं, लेकिन यहाँ एक परीक्षण का मामला है: http://jsperf.com/angularjs-digest/6 जो 10,000 वॉचर्स बनाता है। एक आधुनिक ब्राउज़र पर यह केवल 6 एमएस के अंतर्गत आता है। पर इंटरनेट एक्सप्लोरर 8 यह 40 एमएस के बारे में लेता है। जैसा कि आप देख सकते हैं, यह इन दिनों धीमे ब्राउज़रों पर भी एक मुद्दा नहीं है। एक चेतावनी है: तुलनाओं को समय सीमा में फिट होने के लिए सरल होने की आवश्यकता है ... दुर्भाग्य से एंगुलरजेएस में धीमी तुलना जोड़ना बहुत आसान है, इसलिए धीमी गति से अनुप्रयोगों का निर्माण करना आसान है, जब आप नहीं जानते कि आप क्या हैं कर रहे हैं। लेकिन हम एक इंस्ट्रूमेंटेशन मॉड्यूल प्रदान करके एक उत्तर की उम्मीद करते हैं, जो आपको दिखाएगा कि धीमी तुलनाएं कौन सी हैं।

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


32
@Mark - हाँ, KO में आप सिर्फ .extend ({थ्रॉटल: 500}) जोड़ें, उस पर अभिनय करने से पहले अंतिम परिवर्तन की घटना के बाद 500 मिलीसेकंड तक प्रतीक्षा करें।
डैनियल ईयरविकर

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

10
@DavidRivers हमारे लिए ors वैसे ही है जैसे 1µs = 0.000001s
13'13

33
बयान को आसानी से उल्टा कहा जा सकता है क्योंकि "डर्टी चेकिंग एक समस्या के लिए एक चतुर विशेषता है जो नॉकआउट के पास नहीं है"। ES6 वेधशालाओं का उपयोग कर रहा है और कोणीय गंदी जाँच से छुटकारा पा रहा है। असली दुनिया ने इस जवाब को पकड़ा और झूठा दिखाया।
शंकुधारी

17
"50 एमएस से अधिक तेज कुछ भी मनुष्य के लिए अपरिहार्य है" सच नहीं है। परीक्षण में हमने पाया है कि हमारे ग्राहक आसानी से 50ms अद्यतन विलंबता (20fps) और 16.6ms अद्यतन विलंबता (60fps) के बीच अंतर कर सकते हैं। पूर्व गति से चलने वाले दृश्य लगातार समग्र रूप से खराब हो जाते हैं, "यह कैसा लगा" रेटिंग तब भी जब लोग जानबूझकर फ्रैमर्ट दर्ज नहीं करते थे।
क्रैश ऑक्टर्स

323

मिसको ने पहले से ही एक बेहतरीन विवरण दिया कि डेटा बाइंडिंग कैसे काम करती है, लेकिन मैं डेटा बाइंडिंग के साथ प्रदर्शन के मुद्दे पर अपना दृष्टिकोण जोड़ना चाहूंगा।

जैसा कि मिस्को ने कहा है, लगभग 2000 बाइंडिंग ऐसी हैं जहाँ आप समस्याओं को देखना शुरू करते हैं, लेकिन आपके पास किसी भी पेज पर 2000 से अधिक जानकारी नहीं होनी चाहिए। यह सच हो सकता है, लेकिन प्रत्येक डेटा-बाध्यकारी उपयोगकर्ता को दिखाई नहीं देता है। एक बार जब आप दो तरह से बाध्यकारी के साथ किसी भी प्रकार के विजेट या डेटा ग्रिड का निर्माण शुरू करते हैं, तो आप एक खराब यूएक्स के बिना आसानी से 2000 बाइंडिंग हिट कर सकते हैं

उदाहरण के लिए, एक कॉम्बो बॉक्स पर विचार करें जहाँ आप उपलब्ध विकल्पों को फ़िल्टर करने के लिए टेक्स्ट टाइप कर सकते हैं। इस तरह का नियंत्रण ~ 150 आइटम हो सकता है और अभी भी अत्यधिक उपयोग योग्य हो सकता है। यदि इसमें कुछ अतिरिक्त सुविधा है (उदाहरण के लिए वर्तमान में चयनित विकल्प पर एक विशिष्ट वर्ग) तो आपको प्रति विकल्प 3-5 बाइंडिंग मिलना शुरू हो जाएगा। इनमें से तीन विगेट्स एक पेज पर रखें (जैसे एक देश का चयन करने के लिए, दूसरा उक्त देश में एक शहर का चयन करने के लिए, और तीसरा एक होटल का चयन करने के लिए) और आप कहीं 1000 से 2000 के बीच पहले से मौजूद हैं।

या कॉर्पोरेट वेब एप्लिकेशन में डेटा-ग्रिड पर विचार करें। प्रति पृष्ठ 50 पंक्तियाँ अनुचित नहीं हैं, जिनमें से प्रत्येक में 10-20 कॉलम हो सकते हैं। यदि आप इसे एनजी-रिपीट के साथ बनाते हैं, और / या कुछ कोशिकाओं में जानकारी है जो कुछ बाइंडिंग का उपयोग करता है, तो आप अकेले इस ग्रिड के साथ 2000 बाइंडिंग के करीब पहुंच सकते हैं।

मुझे यह बहुत बड़ा लगता है समस्या है जब मुझे AngularJS के साथ काम , और एकमात्र समाधान जो मुझे अभी तक मिल रहा है, वह है दो तरह से बिना बाध्यकारी के विजेट्स का निर्माण करना, इसके बजाय ngOnce, deregistering पर नजर रखने वाले और इसी तरह के ट्रिक्स का उपयोग करना, या निर्माण करना निर्देश जो jQuery और DOM हेरफेर के साथ DOM का निर्माण करते हैं। मुझे लगता है कि यह पहली जगह में कोणीय का उपयोग करने के उद्देश्य को हरा देता है।

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

TL; DR
डेटा बाइंडिंग जटिल पृष्ठों पर प्रदर्शन समस्याओं का कारण बन सकता है।


26
हाँ मैं यह दूसरा। हमारे ऐप की प्राथमिक जिम्मेदारी विभिन्न संस्थाओं के बीच संबंध प्रदर्शित करना है। किसी दिए गए पृष्ठ में 10 अनुभाग हो सकते हैं। प्रत्येक अनुभाग में एक तालिका है। प्रत्येक टेबल में 2-5 टाइपहेड फिल्टर हैं। प्रत्येक तालिका में 2-5 कॉलम होते हैं, प्रत्येक में 10 पंक्तियाँ होती हैं। बहुत जल्दी हम पूर्ण मुद्दों में भाग लेते हैं, और "समान चाल" विकल्पों के साथ जा रहे हैं।
स्कॉट सिल्वी 15

10
क्या यह कहना उचित है कि कोणीय केवल डेटा बाइंडिंग के बारे में नहीं है और कुछ ऐप इस सुविधा का उपयोग उन कारणों के लिए नहीं करना चाहते हैं, जिनका अन्य ने उल्लेख किया है? मुझे लगता है कि डीआई और प्रतिरूपकता का दृष्टिकोण अपने आप में बहुत कुछ है; मैजिक ऑटो-बाइंडिंग अच्छा है लेकिन हर मौजूदा कार्यान्वयन में प्रदर्शन का व्यापार-बंद है। CRUD के अधिकांश वेब ऐप्स के लिए कोणीय का तरीका यकीनन बेहतर है, और लोग इसे चरम सीमा तक ले जाने की कोशिश कर बस एक दीवार से टकरा रहे हैं। यह सुनकर अच्छा लगेगा कि ईवेंट की वैकल्पिक पद्धति का समर्थन किया गया हो, लेकिन हो सकता है कि यह एक एकल ढांचे के लिए मौलिक रूप से बहुत जटिल हो?
जेसन बोयड

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

6
@MW। ईमानदारी से मुझे लगा कि एक बार कोर में था। लेकिन ऐसा प्रतीत होता है कि यह नहीं है। यह सिर्फ कुछ है जो आप अपने निर्देशों को लिखते समय कर सकते हैं, मूल रूप से सामान को बिना देखे लिंक कर सकते हैं। हालाँकि इसके लिए एक ux mod है: github.com/pasvaz/bindonce
Gaute Løken

9
इसे पढ़ने वाले किसी भी व्यक्ति के लिए भविष्य से एक चिल्लाहट
नोबिता

158

$scopeवस्तु को गंदा करके

कोणीय वस्तुओं arrayमें द्रष्टाओं की एक सरलता बनाए रखता है $scope। यदि आप किसी का निरीक्षण करते हैं तो आप $scopeपाएंगे कि इसमें एक arrayबुलाया गया है $$watchers

प्रत्येक द्रष्टा वह है जो objectअन्य चीजों में शामिल है

  1. एक अभिव्यक्ति जो द्रष्टा निगरानी कर रहा है। यह सिर्फ एक attributeनाम या कुछ और जटिल हो सकता है।
  2. अभिव्यक्ति का एक अंतिम ज्ञात मूल्य। यह अभिव्यक्ति के वर्तमान गणना मूल्य के खिलाफ जाँच की जा सकती है। यदि मान भिन्न होते हैं, तो द्रष्टा फ़ंक्शन को ट्रिगर करेगा और $scopeगंदे के रूप में चिह्नित करेगा ।
  3. एक फ़ंक्शन जिसे यदि द्रष्टा गंदा है तो निष्पादित किया जाएगा।

चौकीदार कैसे परिभाषित होते हैं

AngularJS में एक द्रष्टा को परिभाषित करने के कई अलग-अलग तरीके हैं।

  • आप स्पष्ट रूप से $watchएक attributeपर कर सकते हैं $scope

    $scope.$watch('person.username', validateUnique);
  • आप {{}}अपने टेम्पलेट में एक इंटरपोलेशन रख सकते हैं (वर्तमान पर आपके लिए एक चौकीदार बनाया जाएगा $scope)।

    <p>username: {{person.username}}</p>
  • आप एक निर्देश पूछ सकते हैं जैसे ng-modelआपके लिए चौकीदार को परिभाषित करना।

    <input ng-model="person.username" />

$digestचक्र उनके अंतिम मान के खिलाफ सभी पर नजर रखने वालों की जांच करता है

जब हम सामान्य चैनलों (एनजी-मॉडल, एनजी-रिपीट, आदि) के माध्यम से एंगुलरजेएस के साथ बातचीत करते हैं, तो एक पाचन चक्र निर्देश द्वारा ट्रिगर किया जाएगा।

एक पाचन चक्र गहराई $scopeऔर उसके सभी बच्चों का पहला लक्षण है । प्रत्येक के लिए $scope object, हम इसके बारे में पुनरावृति करते हैं $$watchers arrayऔर सभी अभिव्यक्तियों का मूल्यांकन करते हैं। यदि नई अभिव्यक्ति का मान पिछले ज्ञात मूल्य से अलग है, तो वॉचर्स फ़ंक्शन को कहा जाता है। यह फ़ंक्शन DOM के भाग को फिर से शुरू कर सकता है, एक मान को फिर से शुरू कर सकता है, एक $scopeट्रिगर कर सकता है AJAX request, कुछ भी आपको इसकी आवश्यकता है।

हर गुंजाइश का पता लगाया जाता है और हर घड़ी अभिव्यक्ति का मूल्यांकन किया जाता है और अंतिम मूल्य के खिलाफ जांच की जाती है।

यदि एक द्रष्टा ट्रिगर है, $scopeगंदा है

यदि एक द्रष्टा को ट्रिगर किया जाता है, तो ऐप जानता है कि कुछ बदल गया है, और इसे $scopeगंदे के रूप में चिह्नित किया गया है।

वॉचर फ़ंक्शंस $scopeमाता-पिता पर या अन्य विशेषताओं को बदल सकते हैं $scope। यदि एक $watcherफ़ंक्शन को ट्रिगर किया गया है, तो हम गारंटी नहीं दे सकते कि हमारे अन्य $scopeएस अभी भी साफ हैं, और इसलिए हम पूरे पाचन चक्र को फिर से निष्पादित करते हैं।

ऐसा इसलिए है क्योंकि AngularJS में दो-तरफ़ा बाइंडिंग है, इसलिए डेटा को $scopeट्री के ऊपर वापस भेजा जा सकता है । हम $scopeपहले से पच चुके उच्च पर मान बदल सकते हैं । शायद हम एक मान को बदलते हैं $rootScope

यदि $digestगंदा है, तो हम पूरे $digestचक्र को फिर से निष्पादित करते हैं

हम लगातार $digestचक्र के माध्यम से लूप करते हैं जब तक या तो पाचन चक्र साफ नहीं हो जाता है (सभी $watchअभिव्यक्तियों का समान मूल्य है जैसा कि पिछले चक्र में था), या हम पाचन सीमा तक पहुंचते हैं। डिफ़ॉल्ट रूप से, यह सीमा 10 पर निर्धारित है।

अगर हम डाइजेस्ट लिमिट तक पहुँच जाते हैं तो AngularJS कंसोल में एक त्रुटि उत्पन्न करेगा:

10 $digest() iterations reached. Aborting!

पचाने की मशीन पर मुश्किल है लेकिन डेवलपर पर आसान है

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

मशीन के दृष्टिकोण से हालांकि यह बेतहाशा अक्षम है और अगर हम बहुत सारे वॉचर्स बनाते हैं तो यह हमारे ऐप को धीमा कर देगा। मिसको ने लगभग 4000 वॉचर्स का एक आंकड़ा उद्धृत किया है इससे पहले कि आपका ऐप पुराने ब्राउज़रों पर धीमा महसूस करेगा।

उदाहरण के लिए यदि आप ng-repeatबड़े पैमाने पर पहुँचते हैं तो यह सीमा आसान है JSON array। आप वॉचर्स बनाए बिना किसी टेम्पलेट को संकलित करने के लिए वन-टाइम बाइंडिंग जैसी सुविधाओं का उपयोग करके इसके खिलाफ कम कर सकते हैं।

बहुत सारे चौकीदार बनाने से कैसे बचें

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

यदि आपके पास डेटा है जो शायद ही कभी बदलेगा, तो आप इसे केवल एक बार :: सिंटैक्स का उपयोग करके बाँध सकते हैं, जैसे:

<p>{{::person.username}}</p>

या

<p ng-bind="::person.username"></p>

बंधन केवल ट्रिगर किया जाएगा जब युक्त टेम्पलेट प्रदान किया गया है और डेटा लोड किया गया है $scope

यह विशेष रूप से महत्वपूर्ण है जब आपके पास ng-repeatकई आइटम हों।

<div ng-repeat="person in people track by username">
  {{::person.username}}
</div>

धन्यवाद @ user2864740 - हालांकि यह सही है कि मिस्को का उत्तर शीर्ष होना चाहिए। वह किसी से भी बेहतर फ्रेमवर्क को जानता है, और यह बहुत अच्छा है कि वह स्टैक ओवरफ्लो के साथ संलग्न है ..
सुपरलिमिनरी

4
मैं असहमत हूं कि उत्तर शीर्ष पर होना चाहिए; किसी चीज़ को जानने और किसी विशिष्ट प्रश्न के लिए एक प्रासंगिक / विस्तृत उत्तर लिखने के बीच अंतर होता है। प्रशंसा पाने के बेहतर तरीके हैं। वैसे भी ..
user2864740

1
मुझे संदेह नहीं है कि यह सच है, लेकिन सवाल और जवाब के जवाब सवाल :)
user2864740

3
अच्छा उत्तर यह बताता है कि गंदी-जांच कैसे व्यवहार करती है और इसका वास्तव में मूल्यांकन क्या है, मिस्को के उत्तर में एक बात भी स्पष्ट नहीं थी।
Strider

3
शानदार और विस्तृत जवाब। @superluminary, इस तरह के उत्तर के लिए धन्यवाद। इसके अलावा, इस उत्तर को पढ़ने के बाद, मैं इस बात पर आता हूं कि हमें एक अभिव्यक्ति के रूप में गैर-बेरोजगार अभिव्यक्ति को नहीं जोड़ना चाहिए।
मंगू सिंह राजपुरोहित

81

यह मेरी बुनियादी समझ है। यह गलत हो सकता है!

  1. आइटम किसी फ़ंक्शन को पास करके (देखे जाने वाली चीज़ को लौटाकर) देखे जाते हैं $watch
  2. देखे गए आइटमों में परिवर्तन कोड के एक ब्लॉक के भीतर किया जाना चाहिए जिसे लिपटे हुए हों $applyविधि ।
  3. के अंत में विधि शुरू हो जाती है जो देखता है और चेक से प्रत्येक के माध्यम से चला जाता है अगर वे पिछली बार के बाद से बदल देखने के लिए$apply$digest$digest भाग गया।
  4. यदि कोई परिवर्तन पाया जाता है, तो पाचन को फिर से लागू किया जाता है जब तक कि सभी परिवर्तन स्थिर नहीं हो जाते।

सामान्य विकास में, HTML में डेटा-बाइंडिंग सिंटैक्स AngularJS संकलक को आपके लिए घड़ियाँ बनाने के लिए कहता है और नियंत्रक विधियाँ $applyपहले से ही चल रही हैं । तो एप्लिकेशन डेवलपर के लिए यह सब पारदर्शी है।


4
जब लागू विधि चालू हो जाती है?
अंकन सलाति

3
@EliseuMonar पाचन लूप किसी घटना या कॉल $ लागू () के परिणामस्वरूप चलता है, इसे समय-समय पर टाइमर के आधार पर नहीं कहा जाता है। देखें कि AngularJS की $ वॉच फंक्शन कैसे काम करती है? और एंगुलरजेएस में बाइंडिंग और डाइजेस्ट कैसे काम करता है?
ADL

1
@remi, मैं AngularJS के अंतिम संस्करण के बारे में चिंतित नहीं हूं। वे पहले से ही परदे के पीछे या Object.observe का उपयोग कर रहे हैं? यदि नहीं, तो वे अभी भी गंदे चेकिंग युग में हैं, जो यह देखने के लिए एक समयबद्ध लूप बनाता है कि क्या मॉडल के गुण बदल गए हैं।
एलिसे मोनार डॉस सैंटोस

1
मैं कि डाइजेस्ट की दस बार एक अधिकतम चलेंगे पढ़ा है sitepoint.com/understanding-angulars-apply-digest
user137717

62

मैंने थोड़ी देर के लिए खुद को आश्चर्यचकित किया। बसने वालों के बिना AngularJSसूचना $scopeवस्तु में कैसे बदलती है ? क्या यह उन्हें प्रदूषित करता है?

यह वास्तव में क्या करता है: किसी भी "सामान्य" स्थान पर जिसे आप संशोधित करते हैं, मॉडल पहले से ही हिम्मत से बुलाया गया था AngularJS, इसलिए यह $applyआपके कोड चलने के बाद स्वचालित रूप से आपके लिए कॉल करता है । मान लें कि आपके नियंत्रक के पास एक विधि है जो ng-clickकिसी तत्व पर झुकी हुई है। क्योंकि AngularJSआपके लिए उस तरीके की कॉलिंग को एक साथ जोड़ा जाता है, इसलिए इसके $applyलिए उपयुक्त जगह पर एक मौका है। इसी तरह, उन भावों के लिए, जो विचारों में सही दिखाई देते हैं, उन लोगों द्वारा निष्पादित किया जाता है AngularJSइसलिए यह करता है $apply

जब दस्तावेज़ीकरण $applyकोड के बाहरAngularJS मैन्युअल रूप से कॉल करने की बात करता है, तो यह कोड के बारे में बात कर रहा है, जो जब चलता है, AngularJSकॉल स्टैक में स्वयं से स्टेम नहीं करता है ।


32

चित्रों के साथ व्याख्या:

डेटा-बाइंडिंग को मैपिंग की आवश्यकता होती है

दायरे में संदर्भ टेम्पलेट में संदर्भ बिल्कुल नहीं है। जब आप दो ऑब्जेक्ट को डेटा-बाइंड करते हैं, तो आपको तीसरे की आवश्यकता होती है जो पहले को सुनें और दूसरे को संशोधित करें।

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

यहां, जब आप संशोधित करते हैं <input>, तो आप डेटा-रिफ 3 को स्पर्श करते हैं । और क्लासिक डेटा-बाइंड मेकनिज्म डेटा-रिफंड 4 को बदल देगा । तो अन्य {{data}}भाव कैसे चलेंगे?

घटनाएँ $ पचाने की ओर ले जाती हैं ()

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

कोणीय का कहना है एक oldValueऔर newValueहर बंधन की। और हर कोणीय घटना के बाद , प्रसिद्ध $digest()लूप वॉचस्टलिस्ट की जांच करेगा कि क्या कुछ बदल गया है। ये कोणीय घटनाओं रहे हैं ng-click, ng-change, $httpपूरा ... $digest()इच्छा पाश लंबे किसी भी रूप में के रूप oldValueसे भिन्नnewValue

पिछली तस्वीर में, यह ध्यान देगा कि डेटा-रिफ 1 और डेटा-रिफ 2 बदल गया है।

निष्कर्ष

यह थोड़ा अंडा और चिकन की तरह है। आप कभी नहीं जानते कि कौन शुरू करता है, लेकिन उम्मीद है कि यह उम्मीद के मुताबिक ज्यादातर समय काम करता है।

दूसरा बिंदु यह है कि आप मेमोरी और सीपीयू पर एक सरल बंधन के गहरे प्रभाव को आसानी से समझ सकते हैं। उम्मीद है कि डेस्कटॉप इसे संभालने के लिए काफी मोटे हैं। मोबाइल फोन उतना मजबूत नहीं है।


22

स्पष्ट रूप से इस बात की कोई आवधिक जाँच नहीं है Scopeकि इससे जुड़ी वस्तुओं में कोई बदलाव है या नहीं। गुंजाइश से जुड़ी सभी वस्तुओं को नहीं देखा जाता है। स्कोप प्रोटोटाइप $ $ पहरेदार रखता है । Scopeकेवल $$watchersजब $digestयह कहा जाता है के माध्यम से पुनरावृत्ति ।

कोणीय इनमें से प्रत्येक के लिए $$ देखने वालों को एक द्रष्टा जोड़ता है

  1. {{अभिव्यक्ति}} - आपके टेम्पलेट्स में (और कहीं और जहां एक अभिव्यक्ति है) या जब हम एनजी-मॉडल को परिभाषित करते हैं।
  2. $ गुंजाइश। $ घड़ी ('अभिव्यक्ति / कार्य') - आपके जावास्क्रिप्ट में हम कोणीय को देखने के लिए एक गुंजाइश वस्तु संलग्न कर सकते हैं।

$ घड़ी समारोह तीन मापदंडों में लेता है:

  1. पहला एक वॉचर फ़ंक्शन है जो केवल ऑब्जेक्ट लौटाता है या हम केवल एक अभिव्यक्ति जोड़ सकते हैं।

  2. दूसरा एक श्रोता फ़ंक्शन है जिसे ऑब्जेक्ट में परिवर्तन होने पर बुलाया जाएगा। इस फ़ंक्शन में DOM परिवर्तन जैसी सभी चीजें लागू की जाएंगी।

  3. तीसरा एक वैकल्पिक पैरामीटर है जो बूलियन में लेता है। यदि इसका सही, कोणीय गहन वस्तु को देखता है और यदि इसका झूठा कोणीय सिर्फ वस्तु पर एक संदर्भ देखता है। $ घड़ी का रफ इम्प्लीमेंटेशन इस तरह दिखता है

Scope.prototype.$watch = function(watchFn, listenerFn) {
   var watcher = {
       watchFn: watchFn,
       listenerFn: listenerFn || function() { },
       last: initWatchVal  // initWatchVal is typically undefined
   };
   this.$$watchers.push(watcher); // pushing the Watcher Object to Watchers  
};

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

Scope.prototype.$digest = function() {
      var dirty;
      do {
          dirty = this.$$digestOnce();
      } while (dirty);
}
Scope.prototype.$$digestOnce = function() {
   var self = this;
   var newValue, oldValue, dirty;
   _.forEach(this.$$watchers, function(watcher) {
          newValue = watcher.watchFn(self);
          oldValue = watcher.last;   // It just remembers the last value for dirty checking
          if (newValue !== oldValue) { //Dirty checking of References 
   // For Deep checking the object , code of Value     
   // based checking of Object should be implemented here
             watcher.last = newValue;
             watcher.listenerFn(newValue,
                  (oldValue === initWatchVal ? newValue : oldValue),
                   self);
          dirty = true;
          }
     });
   return dirty;
 };

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

Scope.prototype.$apply = function(expr) {
       try {
         return this.$eval(expr); //Evaluating code in the context of Scope
       } finally {
         this.$digest();
       }
};

15

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

$ घड़ी () : -

इस कार्य का उपयोग $ स्कोप पर एक चर में परिवर्तन का निरीक्षण करने के लिए किया जाता है। यह तीन मापदंडों को स्वीकार करता है: अभिव्यक्ति, श्रोता और समानता ऑब्जेक्ट, जहां श्रोता और समानता ऑब्जेक्ट वैकल्पिक पैरामीटर हैं।

$ पचा () -

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

$ लागू () -

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


7

ऐसा हुआ कि मुझे किसी व्यक्ति के डेटा मॉडल को एक फ़ॉर्म के साथ लिंक करने की आवश्यकता थी, जो मैंने किया वह फ़ॉर्म के साथ डेटा का प्रत्यक्ष मानचित्रण था।

उदाहरण के लिए यदि मॉडल में कुछ ऐसा था:

$scope.model.people.name

प्रपत्र का नियंत्रण इनपुट:

<input type="text" name="namePeople" model="model.people.name">

इस तरह यदि आप ऑब्जेक्ट कंट्रोलर के मान को संशोधित करते हैं, तो यह दृश्य में स्वचालित रूप से परिलक्षित होगा।

एक उदाहरण जहां मैंने मॉडल पारित किया है, सर्वर डेटा से अपडेट किया गया है जब आप लिखित कोड के आधार पर ज़िप कोड और ज़िप कोड मांगते हैं, तो उस दृश्य से जुड़ी कॉलोनियों और शहरों की एक सूची लोड होती है, और डिफ़ॉल्ट रूप से उपयोगकर्ता के साथ पहला मूल्य निर्धारित करता है। और यह मैंने बहुत अच्छी तरह से काम किया, क्या होता है, यह है कि angularJSकभी-कभी मॉडल को ताज़ा करने में कुछ सेकंड लगते हैं, ऐसा करने के लिए आप डेटा प्रदर्शित करते समय एक स्पिनर डाल सकते हैं।


14
मैंने इस उत्तर को 5 बार पढ़ा और मुझे अभी भी समझ नहीं आया कि यहाँ क्या है।
सेडुलिन

1
जवाब मेरे लिए पहेली जैसा है
अमन

6
  1. वन-वे डेटा बाइंडिंग एक दृष्टिकोण है जहां डेटा मॉडल से एक मान लिया जाता है और HTML तत्व में डाला जाता है। मॉडल को देखने से अपडेट करने का कोई तरीका नहीं है। इसका उपयोग शास्त्रीय टेम्पलेट सिस्टम में किया जाता है। ये सिस्टम केवल एक दिशा में डेटा को बांधते हैं।

  2. एंगुलर ऐप में डेटा-बाइंडिंग मॉडल और व्यू घटकों के बीच डेटा का स्वचालित सिंक्रनाइज़ेशन है।

डेटा बाइंडिंग आपको अपने एप्लिकेशन में मॉडल को एकल-स्रोत-सत्य के रूप में व्यवहार करने देता है। दृश्य हर समय मॉडल का एक प्रक्षेपण है। यदि मॉडल बदला गया है, तो दृश्य परिवर्तन को दर्शाता है और इसके विपरीत।


5

इनपुट क्षेत्र का उपयोग करते हुए, एंगुलरजेएस के साथ डेटा बाइंडिंग का एक उदाहरण है। बाद में समझाऊंगा

HTML कोड

<div ng-app="myApp" ng-controller="myCtrl" class="formInput">
     <input type="text" ng-model="watchInput" Placeholder="type something"/>
     <p>{{watchInput}}</p> 
</div>

AngularJS कोड

myApp = angular.module ("myApp", []);
myApp.controller("myCtrl", ["$scope", function($scope){
  //Your Controller code goes here
}]);

जैसा कि आप ऊपर दिए गए उदाहरण में देख सकते हैं, AngularJSng-model HTML तत्वों पर, विशेष रूप से inputखेतों पर क्या होता है , यह सुनने और देखने के लिए उपयोग करता है । जब कुछ होता है, तो कुछ करो। ng-modelमूंछ अंकन का उपयोग करते हुए , हमारे मामले में, हमारे विचार से बाध्य है{{}} । इनपुट फ़ील्ड के अंदर जो भी टाइप किया जाता है वह स्क्रीन पर तुरन्त प्रदर्शित होता है। और यह डेटा बाइंडिंग की सुंदरता है, इसका सरल रूप में एंगुलरजेएस का उपयोग करना।

उम्मीद है की यह मदद करेगा।

कोडपेन पर यहां एक कार्यशील उदाहरण देखें


5

AngularJs दो तरह से डेटा-बाइंडिंग का समर्थन करता है ।
इसका मतलब है कि आप डेटा को देख सकते हैं -> नियंत्रक और नियंत्रक -> दृश्य

एक्स के लिए।

1)

// If $scope have some value in Controller. 
$scope.name = "Peter";

// HTML
<div> {{ name }} </div>

ओ / पी

Peter

आप डेटा को ng-modelपसंद में बाँध सकते हैं : -
2)

<input ng-model="name" />

<div> {{ name }} </div>

यहां ऊपर दिए गए उदाहरण में जो भी इनपुट उपयोगकर्ता देगा, वह <div>टैग में दिखाई देगा ।

यदि आप html को कंट्रोलर से इनपुट बांधना चाहते हैं: -
3)

<form name="myForm" ng-submit="registration()">
   <label> Name </lbel>
   <input ng-model="name" />
</form>

यदि आप nameनियंत्रक में इनपुट का उपयोग करना चाहते हैं तो,

$scope.name = {};

$scope.registration = function() {
   console.log("You will get the name here ", $scope.name);
};

ng-modelहमारे विचार को बांधता है और इसे अभिव्यक्ति में प्रस्तुत करता है {{ }}
ng-modelवह डेटा है जो उपयोगकर्ता को दृश्य में दिखाया जाता है और जिसके साथ उपयोगकर्ता सहभागिता करता है।
इसलिए AngularJs में डेटा को बांधना आसान है।


4

Angular.js हमारे द्वारा देखे जाने वाले प्रत्येक मॉडल के लिए एक द्रष्टा बनाता है। जब भी कोई मॉडल बदला जाता है, तो मॉडल के लिए "एनजी-डर्टी" क्लास को जोड़ा जाता है, इसलिए वॉचर उन सभी मॉडलों का निरीक्षण करेगा, जिनमें क्लास "एनजी-डर्टी" है और कंट्रोलर और इसके विपरीत में उनके मूल्यों को अपडेट करता है।


3

अनिवार्य तथ्य:

डेटा बाइंडिंग क्या है?

जब भी उपयोगकर्ता दृश्य में डेटा को बदलता है, तो स्कोप मॉडल में उस परिवर्तन का एक अद्यतन होता है, और इसके विपरीत।

यह कैसे संभव है?

संक्षिप्त जवाब : पाचन चक्र की सहायता से।

विवरण: कोणीय js स्कोपर को स्कोप मॉडल पर सेट करता है, जो मॉडल में बदलाव होने पर श्रोता के कार्य को आग देता है।

$scope.$watch('modelVar' , function(newValue,oldValue){

// नए मूल्य के साथ डोम अपडेट कोड

});

तो चौकीदार कब और कैसे कहा जाता है?

वॉचर फ़ंक्शन को पाचन चक्र के भाग के रूप में कहा जाता है।

डाइजेस्ट चक्र को स्वचालित रूप से ट्रिगर किया जाता है जिसे एनजी-मॉडल, एनजी-मॉडल, एनजी-बाइंड, $ टाइमआउट, एनजी-क्लिक और अन्य जैसे निर्देशों / सेवाओं में बनाया गया है .. जो आपको पाचन चक्र को ट्रिगर करते हैं।

पाचन चक्र समारोह:

$scope.$digest() -> digest cycle against the current scope.
$scope.$apply() -> digest cycle against the parent scope 

अर्थात$rootScope.$apply()

नोट: $ लागू () $ rootScope के बराबर है। $ डाइजेस्ट () इसका मतलब है कि गंदे चेकिंग रूट या टॉप से ​​शुरू होती है या पैरेंट स्कोप को कोणीय js एप्लीकेशन में सभी बच्चे $ scopes के नीचे रखते हैं।

उपर्युक्त विशेषताएं ब्राउज़रों IE में उल्लेख किए गए संस्करणों के लिए भी काम करती हैं, यह सुनिश्चित करने के लिए कि आपका एप्लिकेशन कोणीय js अनुप्रयोग है जिसका अर्थ है कि आप स्क्रिप्ट टैग में संदर्भित angularjs फ्रेमवर्क स्क्रिप्ट फ़ाइल का उपयोग कर रहे हैं।

धन्यवाद।

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