javascript - AngularJS में डेटा बाध्यकारी कार्य कैसे करता है?
data-binding (9)
AngularJS
ढांचे में डेटा बाध्यकारी काम कैसे करता है?
मुझे उनकी साइट पर तकनीकी विवरण नहीं मिला है। जब डेटा को मॉडल से देखने के लिए प्रचारित किया जाता है तो यह कम या ज्यादा स्पष्ट होता है। लेकिन AngularJS कैसे सेटर्स और गेटर्स के बिना मॉडल गुणों में परिवर्तन करता है?
मैंने पाया कि जावास्क्रिप्ट वॉचर्स हैं जो यह काम कर सकते हैं। लेकिन वे Internet Explorer 6 और Internet Explorer 7 में समर्थित नहीं हैं। तो AngularJS कैसे जानता है कि मैंने उदाहरण के लिए निम्नलिखित बदल दिया और इस बदलाव को एक दृश्य पर प्रतिबिंबित किया?
myobject.myproperty="new value";
गंदे द्वारा $scope
ऑब्जेक्ट की जांच कर रहा है
कोणीय $scope
ऑब्जेक्ट्स में वॉचर्स की एक साधारण array
रखता है। यदि आप किसी भी $scope
का निरीक्षण करते हैं तो आप पाएंगे कि इसमें $$watchers
नामक एक array
।
प्रत्येक दर्शक एक object
है जिसमें अन्य चीजों के बीच होता है
- एक अभिव्यक्ति जो वॉचर निगरानी कर रही है। यह सिर्फ एक
attribute
नाम हो सकता है, या कुछ और जटिल हो सकता है। - अभिव्यक्ति का अंतिम ज्ञात मूल्य। यह अभिव्यक्ति के वर्तमान गणना मूल्य के खिलाफ जांच की जा सकती है। यदि मूल्य भिन्न होते हैं तो दर्शक फ़ंक्शन को ट्रिगर करेगा और
$scope
को गंदे के रूप में चिह्नित करेगा। - एक कार्य जो निष्पादित किया जाएगा यदि दर्शक गंदा है।
कैसे निरीक्षक परिभाषित किया जाता है
AngularJS में एक दर्शक को परिभाषित करने के कई अलग-अलग तरीके हैं।
आप स्पष्ट
attribute
से$scope
पर एकattribute
$watch
सकते हैं।$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
पर एक मूल्य $rootScope
।
अगर $digest
गंदा है, तो हम फिर से पूरे $digest
चक्र को निष्पादित करते हैं
जब तक पाचन चक्र साफ नहीं होता है तब तक हम लगातार $digest
चक्र के माध्यम से लूप करते हैं (सभी $watch
अभिव्यक्तियों के समान चक्र के समान मूल्य होता है), या हम पाचन सीमा तक पहुंचते हैं। डिफ़ॉल्ट रूप से, यह सीमा 10 पर सेट है।
यदि हम पाचन सीमा तक पहुंचते हैं तो AngularJS कंसोल में एक त्रुटि उठाएगा:
10 $digest() iterations reached. Aborting!
पाचन मशीन पर मुश्किल है लेकिन डेवलपर पर आसान है
जैसा कि आप देख सकते हैं, हर बार एंगुलरजेएस ऐप में कुछ बदलाव होता है, एंगुलरजेएस $scope
पदानुक्रम में प्रत्येक वॉचर को जवाब देने के तरीके को देखने के लिए जांच करेगा। एक डेवलपर के लिए यह एक बड़े उत्पादकता वरदान है, क्योंकि अब आपको लगभग कोई वायरिंग कोड लिखने की आवश्यकता नहीं है, एंगुलरजेएस सिर्फ यह ध्यान देगा कि कोई मान बदल गया है, और बाकी ऐप को बदलाव के अनुरूप बनाते हैं।
मशीन के परिप्रेक्ष्य से हालांकि यह जंगली रूप से अक्षम है और यदि हम बहुत सारे दर्शक बनाते हैं तो हमारे ऐप को धीमा कर देंगे। आपके ऐप पुराने ब्राउज़रों पर धीमा महसूस करने से पहले मिस्को ने लगभग 4000 वॉचर्स का आंकड़ा उद्धृत किया है।
उदाहरण के लिए यदि आप एक बड़े JSON
array
पर ng-repeat
करते हैं तो यह सीमा तक पहुंच आसान है। आप वॉचर्स बनाये बिना टेम्पलेट को संकलित करने के लिए एक बार बाध्यकारी जैसी सुविधाओं का उपयोग करके इसके खिलाफ कम कर सकते हैं।
बहुत सारे दर्शक बनाने से कैसे बचें
प्रत्येक बार जब आपका उपयोगकर्ता आपके ऐप से इंटरैक्ट करता है, तो आपके ऐप में प्रत्येक वॉचर का मूल्यांकन कम से कम एक बार किया जाएगा। एंगुलरजेएस ऐप को अनुकूलित करने का एक बड़ा हिस्सा आपके $scope
पेड़ में वॉचर्स की संख्या को कम कर रहा है। ऐसा करने का एक आसान तरीका एक बार बाध्यकारी है ।
यदि आपके पास डेटा है जो शायद ही कभी बदल जाएगा, तो आप इसे :: सिंटैक्स का उपयोग करके केवल एक बार बांध सकते हैं, जैसे:
<p>{{::person.username}}</p>
या
<p ng-bind="::person.username"></p>
बाध्यकारी केवल तभी ट्रिगर किया जाएगा जब युक्त टेम्पलेट प्रदान किया जाता है और डेटा $scope
में लोड होता $scope
।
यह विशेष रूप से महत्वपूर्ण है जब आपके पास कई वस्तुओं के साथ ng-repeat
।
<div ng-repeat="person in people track by username">
{{::person.username}}
</div>
एक तरफा डेटा बाइंडिंग एक ऐसा दृष्टिकोण है जहां डेटा मॉडल से मूल्य लिया जाता है और HTML तत्व में डाला जाता है। मॉडल को देखने से अपडेट करने का कोई तरीका नहीं है। यह शास्त्रीय टेम्पलेट सिस्टम में प्रयोग किया जाता है। ये सिस्टम केवल एक दिशा में डेटा बांधते हैं।
कोणीय ऐप्स में डेटा बाध्यकारी मॉडल के बीच डेटा का स्वचालित सिंक्रनाइज़ेशन और घटकों को देखने के लिए है।
डेटा बाध्यकारी आपको मॉडल को अपने एप्लिकेशन में एकल-स्रोत-सत्य के रूप में पेश करने देता है। दृश्य हर समय मॉडल का प्रक्षेपण है। यदि मॉडल बदल गया है, तो दृश्य परिवर्तन को दर्शाता है और इसके विपरीत।
AngularJS तीन शक्तिशाली कार्यों की सहायता से डेटा-बाइंडिंग तंत्र को संभालता है: $watch() , $digest() और $apply() । अधिकांश समय AngularJS $ scope को कॉल करेगा। $ Watch () और $ scope। $ Digest (), लेकिन कुछ मामलों में आपको इन मानों को मैन्युअल रूप से नए मानों के साथ अपडेट करने के लिए कॉल करना पड़ सकता है।
$ घड़ी () : -
इस फ़ंक्शन का उपयोग $ स्कोप पर एक चर में परिवर्तनों का निरीक्षण करने के लिए किया जाता है। यह तीन मानकों को स्वीकार करता है: अभिव्यक्ति, श्रोता और समानता वस्तु, जहां श्रोता और समानता वस्तु वैकल्पिक पैरामीटर हैं।
$ पाचन () -
यह फ़ंक्शन $ स्कोप ऑब्जेक्ट में सभी घड़ियों और उसके बच्चे $ स्कोप ऑब्जेक्ट्स के माध्यम से पुनरावृत्त करता है
(अगर इसमें कोई है)। जब $ पाचन () घड़ियों पर पुनरावृत्त होता है, तो यह जांचता है कि अभिव्यक्ति का मूल्य बदल गया है या नहीं। यदि मान बदल गया है, तो AngularJS श्रोता को नए मान और पुराने मान के साथ कॉल करता है। $ Digest () फ़ंक्शन को तब भी कहा जाता है जब AngularJS सोचता है कि यह आवश्यक है। उदाहरण के लिए, बटन क्लिक करने के बाद, या AJAX कॉल के बाद। आपके पास कुछ ऐसे मामले हो सकते हैं जहां AngularJS आपके लिए $ digest () फ़ंक्शन नहीं कहता है। उस स्थिति में आपको इसे स्वयं कॉल करना होगा।
$ आवेदन () -
कोणीय ऑटो-जादुई रूप से केवल उन मॉडल परिवर्तनों को अपडेट करता है जो AngularJS संदर्भ के अंदर हैं। जब आप कोणीय संदर्भ (जैसे ब्राउज़र DOM ईवेंट, सेटटाइमआउट, एक्सएचआर या तृतीय पक्ष पुस्तकालयों) के बाहर किसी भी मॉडल में परिवर्तन करते हैं, तो आपको मैन्युअल रूप से $ लागू () को कॉल करके परिवर्तनों के कोणीय को सूचित करने की आवश्यकता होती है। जब $ लागू () फ़ंक्शन कॉल समाप्त होता है AngularJS आंतरिक रूप से $ digest () को कॉल करता है, इसलिए सभी डेटा बाइंडिंग अपडेट की जाती हैं।
AngularJS मान को याद करता है और इसे पिछले मान से तुलना करता है। यह मूल गंदा जांच है। यदि मूल्य में कोई बदलाव है, तो यह परिवर्तन घटना को सक्रिय करता है।
$apply()
विधि, जिसे आप गैर-कोणीय जेएस दुनिया से एंगुलरजेएस दुनिया में परिवर्तित करते समय कॉल करते हैं, $digest()
। एक पाचन सिर्फ सादा पुरानी गंदा जांच है। यह सभी ब्राउज़रों पर काम करता है और पूरी तरह अनुमानित है।
गंदे-जांच (एंगुलरजेएस) बनाम श्रोताओं को बदलने के लिए ( KnockoutJS और Backbone.js ): जबकि गंदा जांच सरल लग सकती है, और यहां तक कि अक्षम (मैं बाद में इसे संबोधित करूंगा), यह पता चला है कि यह हर समय अर्थपूर्ण रूप से सही है, जबकि श्रोताओं के पास बहुत सारे अजीब कोने के मामले हैं और इसे निर्भरता ट्रैकिंग जैसी चीजों की आवश्यकता है ताकि इसे अधिक अर्थपूर्ण रूप से सही बनाया जा सके। KnockoutJS निर्भरता ट्रैकिंग एक समस्या के लिए एक चालाक सुविधा है जो AngularJS नहीं है।
परिवर्तन श्रोताओं के साथ मुद्दे:
- वाक्यविन्यास अत्याचारी है, क्योंकि ब्राउज़र इसे मूल रूप से समर्थन नहीं करते हैं। हां, प्रॉक्सी हैं, लेकिन वे सभी मामलों में अर्थात् सही नहीं हैं, और निश्चित रूप से पुराने ब्राउज़र पर कोई प्रॉक्सी नहीं है। निचली पंक्ति यह है कि गंदा जांच आपको POJO करने की अनुमति देती है, जबकि नॉकआउटजेएस और बैकबोन.जेएस आपको अपनी कक्षाओं से प्राप्त करने के लिए मजबूर करते हैं, और एक्सेसर्स के माध्यम से अपने डेटा तक पहुंचते हैं।
- सहवास बदलें। मान लें कि आपके पास वस्तुओं की एक श्रृंखला है। मान लें कि आप एक सरणी में आइटम जोड़ना चाहते हैं, क्योंकि आप जोड़ने के लिए लूपिंग कर रहे हैं, हर बार जब आप जोड़ते हैं तो आप बदलाव पर घटनाओं को फायर कर रहे हैं, जो यूआई को प्रस्तुत कर रहा है। यह प्रदर्शन के लिए बहुत बुरा है। आप जो चाहते हैं वह अंत में केवल एक बार यूआई अपडेट करना है। परिवर्तन की घटनाएं बहुत अच्छी हैं।
- श्रोताओं को तुरंत एक सेटर पर आग लगाना, जो एक समस्या है, क्योंकि परिवर्तन श्रोता डेटा को और बदल सकता है, जो अधिक परिवर्तन घटनाओं को सक्रिय करता है। यह आपके स्टैक पर खराब है क्योंकि आपके पास कई बदलाव घटनाएं हो सकती हैं। मान लें कि आपके पास दो एरे हैं जिन्हें किसी भी कारण से सिंक में रखा जाना चाहिए। आप केवल एक या दूसरे में जोड़ सकते हैं, लेकिन हर बार जब आप एक बदलाव घटना को आग लगाते हैं, जो अब दुनिया का एक असंगत दृश्य है। थ्रेड लॉकिंग के लिए यह एक बहुत ही समान समस्या है, जो जावास्क्रिप्ट से बचाता है क्योंकि प्रत्येक कॉलबैक विशेष रूप से और पूरा होने के लिए निष्पादित होता है। ईवेंट बदलें इसे तोड़ दें क्योंकि सेटर के पास दूरगामी परिणाम हो सकते हैं जो इरादे से नहीं हैं और स्पष्ट नहीं हैं, जो थ्रेड समस्या को फिर से बनाता है। यह पता चला है कि आप क्या करना चाहते हैं श्रोता निष्पादन में देरी करना, और गारंटी है कि केवल एक श्रोता एक समय में चलता है, इसलिए कोई भी कोड डेटा बदलने के लिए स्वतंत्र है, और यह जानता है कि ऐसा कोई अन्य कोड नहीं चल रहा है ।
प्रदर्शन के बारे में क्या?
तो ऐसा लगता है कि हम धीमे हैं, क्योंकि गंदा जांच अक्षम है। यह वह जगह है जहां हमें केवल सैद्धांतिक तर्कों की बजाय वास्तविक संख्याओं को देखने की आवश्यकता है, लेकिन पहले कुछ बाधाओं को परिभाषित करते हैं।
मनुष्य हैं:
धीमा - 50 एमएस से भी तेज कुछ भी इंसानों के लिए अतिसंवेदनशील है और इस प्रकार इसे "तत्काल" माना जा सकता है।
सीमित - आप वास्तव में एक पृष्ठ पर किसी मानव को जानकारी के 2000 से अधिक टुकड़े नहीं दिखा सकते हैं। उससे भी ज्यादा कुछ वास्तव में खराब यूआई है, और मनुष्य वैसे भी इसे संसाधित नहीं कर सकते हैं।
तो वास्तविक सवाल यह है: 50 एमएस में ब्राउज़र पर आप कितनी तुलना कर सकते हैं? जवाब देने के लिए यह एक कठिन सवाल है क्योंकि कई कारक खेलते हैं, लेकिन यहां एक टेस्ट केस है: http://jsperf.com/angularjs-digest/6 जो 10,000 दर्शक बनाता है। एक आधुनिक ब्राउज़र पर यह केवल 6 एमएस से कम लेता है। Internet Explorer 8 इसमें लगभग 40 एमएस लगते हैं। जैसा कि आप देख सकते हैं, यह इन दिनों धीमे ब्राउज़र पर भी कोई मुद्दा नहीं है। एक चेतावनी है: तुलना को समय सीमा में फिट करने के लिए सरल होना आवश्यक है ... दुर्भाग्य से एंगुलरजेएस में धीमी तुलना जोड़ने के लिए यह बहुत आसान है, इसलिए धीमे अनुप्रयोगों को बनाना आसान है जब आप नहीं जानते कि आप क्या जानते हैं कर रहे हैं। लेकिन हमें एक उपकरण मॉड्यूल प्रदान करके एक उत्तर देने की उम्मीद है, जो आपको दिखाएगा कि धीमी तुलना कौन सा है।
यह पता चला है कि वीडियो गेम और जीपीयू गंदे-जांच दृष्टिकोण का उपयोग करते हैं, खासकर क्योंकि यह सुसंगत है। जब तक वे मॉनिटर रीफ्रेश दर (आमतौर पर 50-60 हर्ट्ज, या हर 16.6-20 एमएस) पर पहुंच जाते हैं, तब तक कोई भी प्रदर्शन एक अपशिष्ट है, इसलिए आप एफपीएस उच्च होने की तुलना में अधिक सामान खींचने से बेहतर होते हैं।
एक इनपुट फ़ील्ड का उपयोग करके AngularJS के साथ बाध्यकारी डेटा का एक उदाहरण यहां दिया गया है। मैं बाद में समझाऊंगा
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
}]);
जैसा कि आप ऊपर दिए गए उदाहरण में देख सकते हैं, AngularJS HTML तत्वों पर विशेष रूप से input
फ़ील्ड पर क्या होता है सुनने और देखने के लिए ng-model
का उपयोग करता है। जब कुछ होता है, तो कुछ करो। हमारे मामले में, मूंछ नोटेशन {{}}
का उपयोग करते हुए, ng-model
हमारे विचार से जुड़ा हुआ है। जो भी इनपुट फ़ील्ड के अंदर टाइप किया गया है उसे तुरंत स्क्रीन पर प्रदर्शित किया जाता है। और यह AngularJS का उपयोग अपने सबसे सरल रूप में, डेटा बाध्यकारी की सुंदरता है।
उम्मीद है की यह मदद करेगा।
Codepen पर यहां एक कामकाजी उदाहरण देखें
ऐसा हुआ कि मुझे किसी व्यक्ति के डेटा मॉडल को एक फॉर्म से जोड़ने की ज़रूरत थी, जो मैंने किया था, वह फ़ॉर्म के साथ डेटा का सीधा मैपिंग था।
उदाहरण के लिए यदि मॉडल में कुछ ऐसा था:
$scope.model.people.name
फॉर्म का नियंत्रण इनपुट:
<input type="text" name="namePeople" model="model.people.name">
इस तरह यदि आप ऑब्जेक्ट नियंत्रक के मान को संशोधित करते हैं, तो यह दृश्य में स्वचालित रूप से दिखाई देगा।
एक उदाहरण जहां मैंने मॉडल पारित किया है, सर्वर डेटा से अद्यतन किया जाता है जब आप लिखित भार के आधार पर ज़िप कोड और ज़िप कोड के लिए पूछते हैं, जो उस दृश्य से जुड़े कॉलोनियों और शहरों की एक सूची है, और डिफ़ॉल्ट रूप से उपयोगकर्ता के साथ पहला मान सेट करता है। और यह मैंने बहुत अच्छा काम किया, क्या होता है, यह है कि angularJS
कभी-कभी मॉडल को रीफ्रेश करने के लिए कुछ सेकंड लगते हैं, ऐसा करने के लिए आप डेटा प्रदर्शित करते समय स्पिनर डाल सकते हैं।
मिस्को ने डेटा बाइंडिंग कैसे काम किया है, इस बारे में एक उत्कृष्ट विवरण दिया है, लेकिन मैं डेटा बाध्यकारी के साथ प्रदर्शन समस्या पर अपना विचार जोड़ना चाहता हूं।
जैसा कि मिस्को ने कहा, लगभग 2000 बाइंडिंग्स है जहां आप समस्याओं को देखना शुरू करते हैं, लेकिन आपके पास किसी पृष्ठ पर 2000 से अधिक जानकारी की जानकारी नहीं होनी चाहिए। यह सच हो सकता है, लेकिन उपयोगकर्ता के लिए प्रत्येक डेटा-बाध्यकारी दिखाई नहीं दे रहा है। एक बार जब आप किसी भी प्रकार के विजेट या डेटा ग्रिड को दो-तरफा बाध्यकारी के साथ बनाना शुरू कर देते हैं तो आप खराब ux के बिना 2000 बाइंडिंग आसानी से हिट कर सकते हैं ।
उदाहरण के लिए, एक combobox पर विचार करें जहां आप उपलब्ध विकल्पों को फ़िल्टर करने के लिए टेक्स्ट टाइप कर सकते हैं। इस तरह के नियंत्रण में ~ 150 आइटम हो सकते हैं और अभी भी अत्यधिक उपयोग योग्य हो सकते हैं। यदि इसमें कुछ अतिरिक्त सुविधा है (उदाहरण के लिए वर्तमान में चयनित विकल्प पर एक विशिष्ट श्रेणी) तो आप प्रति विकल्प 3-5 बाइंडिंग प्राप्त करना शुरू कर देते हैं। इन तीनों विजेटों को एक पृष्ठ पर रखें (उदाहरण के लिए एक देश का चयन करने के लिए, दूसरा देश में एक शहर का चयन करने के लिए, और तीसरा होटल चुनने के लिए) और आप कहीं 1000 और 2000 बाइंडिंग के बीच कहीं हैं।
या कॉर्पोरेट वेब एप्लिकेशन में डेटा-ग्रिड पर विचार करें। प्रति पृष्ठ 50 पंक्तियां अनुचित नहीं हैं, जिनमें से प्रत्येक में 10-20 कॉलम हो सकते हैं। यदि आप इसे एनजी-दोहराने के साथ बनाते हैं, और / या कुछ बाइंडिंग का उपयोग करने वाली कुछ कोशिकाओं में जानकारी है, तो आप अकेले इस ग्रिड के साथ 2000 बाइंडिंग तक पहुंच सकते हैं।
मुझे एंगुलरजेएस के साथ काम करते समय यह एक बड़ी समस्या है, और एकमात्र समाधान जिसे मैं अब तक ढूंढने में सक्षम हूं, दो तरह के बाध्यकारी का उपयोग किए बिना विगेट्स का निर्माण करना है, बजाय एनजीओन्स का उपयोग करना, वॉचर्स और इसी तरह की चालों को अपनाना, या निर्देश बनाना जो jQuery और डोम हेरफेर के साथ डोम बनाता है। मुझे लगता है कि यह पहले स्थान पर कोणीय का उपयोग करने के उद्देश्य को हरा देता है।
मुझे इसे संभालने के अन्य तरीकों पर सुझाव सुनना अच्छा लगेगा, लेकिन फिर मुझे अपना खुद का प्रश्न लिखना चाहिए। मैं इसे एक टिप्पणी में रखना चाहता था, लेकिन यह उस के लिए रास्ता बहुत लंबा हो गया ...
टी एल; डॉ
डेटा बाध्यकारी जटिल पृष्ठों पर प्रदर्शन मुद्दों का कारण बन सकता है।
मैंने थोड़ी देर के लिए यह खुद को सोचा। सेटर्स के बिना AngularJS
नोटिस $scope
ऑब्जेक्ट में कैसे बदलता है? क्या यह उन्हें मतदान करता है?
यह वास्तव में क्या करता है यह है: मॉडल को संशोधित करने वाला कोई भी "सामान्य" स्थान पहले से ही AngularJS के गले से बुलाया गया था, इसलिए यह आपके कोड चलाने के बाद स्वचालित रूप से आपके लिए $apply
। मान लें कि आपके कंट्रोलर की एक विधि है जो कुछ तत्वों पर ng-click
करने के लिए ng-click
है। चूंकि एंगुलरजेएस आपके लिए उस विधि को एक साथ बुलाता है, $apply
उसे उचित जगह पर $apply
करने का मौका मिलता है। इसी प्रकार अभिव्यक्तियों के लिए जो विचारों में सही दिखाई देते हैं, उन्हें एंगुलरजेएस द्वारा निष्पादित किया जाता है, इसलिए यह $apply
।
जब एंगुलरजेएस के बाहर कोड के लिए मैन्युअल रूप से $apply
कॉल करने के बारे में प्रलेखन बात करते हैं, तो यह कोड के बारे में बात कर रहा है, जो दौड़ते समय, कॉलर स्टैक में एंगुलरजेएस से स्वयं नहीं होता है।
स्पष्ट रूप से Scope
की कोई आवधिक जांच नहीं है कि इससे जुड़े ऑब्जेक्ट्स में कोई बदलाव है या नहीं। गुंजाइश से जुड़ी सभी वस्तुओं को देखा नहीं जाता है। स्कोप प्रोटोटाइपिक रूप से $$ वॉचर्स रखता है। जब $digest
को बुलाया जाता है तो Scope
केवल $$watchers
वॉचर्स के माध्यम से पुनरावृत्त होता है।
कोणीय इनमें से प्रत्येक के लिए $$ निरीक्षक को एक वॉचर जोड़ता है
- {{अभिव्यक्ति}} - आपके टेम्पलेट्स (और कहीं और जहां एक अभिव्यक्ति है) में या जब हम एनजी-मॉडल को परिभाषित करते हैं।
- $ स्कोप। $ घड़ी ('अभिव्यक्ति / फ़ंक्शन') - आपकी जावास्क्रिप्ट में हम केवल कोणीय देखने के लिए एक स्कोप ऑब्जेक्ट संलग्न कर सकते हैं।
$ घड़ी फ़ंक्शन तीन पैरामीटर में लेता है:
पहला एक वॉचर फ़ंक्शन है जो ऑब्जेक्ट देता है या हम केवल एक अभिव्यक्ति जोड़ सकते हैं।
दूसरा एक श्रोता समारोह है जिसे ऑब्जेक्ट में कोई परिवर्तन होने पर बुलाया जाएगा। डीओएम परिवर्तन जैसी सभी चीजें इस समारोह में लागू की जाएंगी।
तीसरा एक वैकल्पिक पैरामीटर है जो बुलियन में होता है। यदि यह सच है, कोणीय गहरी वस्तु को देखता है और यदि इसका झूठा कोणीय वस्तु पर एक संदर्भ देखता है। $ घड़ी का असर कार्यान्वयन इस तरह दिखता है
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
};
अंगुलर में डाइजेस्ट साइकिल नामक एक दिलचस्प बात है। $ पाचन चक्र के कॉल के परिणामस्वरूप $ पाचन चक्र शुरू होता है। $ Digest ()। मान लें कि आप एनजी-क्लिक निर्देश के माध्यम से एक हैंडलर फ़ंक्शन में $ स्कोप मॉडल बदलते हैं। उस स्थिति में AngularJS स्वचालित रूप से $ digest () को कॉल करके $ पाचन चक्र को ट्रिगर करता है। एनजी-क्लिक के अलावा, कई अन्य अंतर्निहित निर्देश / सेवाएं हैं जो आपको मॉडल बदलने देती हैं (जैसे एनजी-मॉडल, $ टाइमआउट, आदि) और स्वचालित रूप से एक $ पाचन चक्र ट्रिगर। $ पाचन का मोटा कार्यान्वयन इस तरह दिखता है।
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;
};
यदि हम स्कोप मॉडल को अपडेट करने के लिए जावास्क्रिप्ट के सेटटाइमआउट () फ़ंक्शन का उपयोग करते हैं, तो एंगुलर को यह जानने का कोई तरीका नहीं है कि आप क्या बदल सकते हैं। इस मामले में मैन्युअल रूप से $ लागू () को कॉल करने की हमारी ज़िम्मेदारी है, जो $ पाचन चक्र को ट्रिगर करता है। इसी तरह, यदि आपके पास कोई निर्देश है जो एक डोम ईवेंट श्रोता सेट करता है और हैंडलर फ़ंक्शन के अंदर कुछ मॉडल बदलता है, तो परिवर्तनों को प्रभावी बनाने के लिए आपको $ लागू () को कॉल करने की आवश्यकता होती है। $ आवेदन का बड़ा विचार यह है कि हम कुछ कोड निष्पादित कर सकते हैं जो कोणीय से अवगत नहीं है, वह कोड अभी भी दायरे पर चीजें बदल सकता है। अगर हम $ कोड में उस कोड को लपेटते हैं, तो यह $ digest () को कॉल करने का ख्याल रखेगा। $ लागू () के कठिन कार्यान्वयन।
Scope.prototype.$apply = function(expr) {
try {
return this.$eval(expr); //Evaluating code in the context of Scope
} finally {
this.$digest();
}
};