$ application () و $ digest () هما مفهومين أساسيان في AngularJS ، ولكن في بعض الأحيان يكونان مربكين. من أجل فهم كيفية عمل AngularJS ، تحتاج أولاً إلى فهم كيفية تطبيق $ () و $ digest (). تهدف هذه المقالة إلى شرح ما هي $ application () و $ digest () ، وكيف يتم تطبيقها في الترميز اليومي.
1. استكشاف $ application () و $ digest ()
1.1. فهم ربط البيانات ثنائية الاتجاه و Watch () ؛
يوفر AngularJS ميزة رائعة للغاية تسمى ربط البيانات ثنائية الاتجاه ، والتي تبسط بشكل كبير كيف نكتب رمزنا. يعني ربط البيانات أنه عندما يتغير أي بيانات في العرض ، سيتم إعادة التغيير تلقائيًا إلى بيانات النطاق ، مما يعني أنه سيتم تحديث نموذج النطاق تلقائيًا. وبالمثل ، عندما يتغير نموذج النطاق ، يتم تحديث البيانات في العرض إلى أحدث قيمة. فكيف يفعل AngularJS هذا؟ عندما تكتب تعبيرًا مثل {{Amodel}} ، ستقوم AngularJs بتعيين مراقب لك على نموذج النطاق ، والذي يتم استخدامه لتحديث العرض عند تغيير البيانات. المراقب هنا هو نفس المراقب الذي ستضعه في AngularJS:
$ scope. $ watch ('amodel' ، function (newValue ، OldValue) {// reputed the dom with newValue}) ؛المعلمة الثانية التي تم تمريرها إلى $ watch () هي وظيفة رد الاتصال ، والتي سيتم استدعاؤها عندما تتغير قيمة Amodel. عندما يتغير Amodel ، ليس من الصعب فهم أن وظيفة رد الاتصال هذه سيتم استدعاؤها لتحديث العرض ، ولكن لا تزال هناك مشكلة مهمة للغاية! كيف تعرف AngularJS متى تسمي وظيفة رد الاتصال هذه؟ بمعنى آخر ، كيف استدعى AngularJS وظيفة رد الاتصال المقابلة عندما يعلم أن Amodel قد تغير؟ هل ستدير وظيفة بشكل دوري للتحقق مما إذا كانت البيانات الموجودة في نموذج النطاق قد تغيرت؟ حسنًا ، هذا هو المكان الذي تأتي فيه حلقة $ Digest.
في حلقة $ Digest ، سيتم إطلاق المراقبين. عندما يتم تشغيل مراقب ، سوف يكتشف AngularJs نموذج النطاق. إذا تغيرت ، سيتم استدعاء وظيفة رد الاتصال المرتبطة بالمحاذاة. لذا ، فإن السؤال التالي هو متى تبدأ حلقة $ Digest بطرق مختلفة؟
بعد استدعاء نطاق $. $ Digest () ، تبدأ حلقة $ Digest. لنفترض أنك تقوم بتغيير البيانات في نطاق في وظيفة المعالج المقابلة لتوجيه NG-Click ، ستؤدي AngularJS تلقائيًا إلى تشغيل حلقة $ Digest عن طريق الاتصال بـ $ Digest (). عندما تبدأ حلقة $ Digest ، فإنها تثير كل مراقب. سيقوم هؤلاء المراقبون بالتحقق مما إذا كانت قيمة النموذج الحالية في النطاق تختلف عن قيمة النموذج المحسوبة في المرة الأخيرة. إذا كان الأمر مختلفًا ، فسيتم تنفيذ وظيفة رد الاتصال المقابلة. نتيجة استدعاء هذه الوظيفة هي أنه سيتم تحديث محتوى التعبير في العرض (ملاحظة المترجم: مثل {{Amodel}}). بالإضافة إلى توجيه NG-Click ، هناك بعض التوجيهات والخدمات المدمجة الأخرى للسماح لك بتغيير النماذج (مثل NG-Model ، $ Timeout ، وما إلى ذلك) وتشغيل حلقة $ Digest تلقائيًا.
حتى الآن ليس سيئًا! ومع ذلك ، هناك مشكلة صغيرة. في المثال أعلاه ، لا يتصل AngularJS $ digest () مباشرة ، ولكنه يتصل بمجموعة $. لذلك ، تبدأ حلقة $ Digest عند $ rootscope ، والتي ستصل بعد ذلك إلى جميع مراقبي نطاق الأطفال.
ملاحظة: Scope $. $ Apply () سوف يتصل تلقائيًا $ rootscope. $ Digest ().
طريقة $ application () لها نموذجان:
أول واحد سوف يقبل وظيفة كمعلمة ، وتنفيذ الوظيفة وتشغيل حلقة $ digest.
لن يقبل النوع الثاني أي معلمات ويؤدي فقط إلى تشغيل حلقة $ Digest. سنرى على الفور لماذا النموذج الأول أفضل.
1.2. متى يتم الاتصال يدويًا بالطريقة $ application ()؟
إذا كان AngularJS يلفون رمزنا دائمًا في وظيفة وتمريره في $ application () لبدء حلقة $ digest ، فمتى نحتاج إلى استدعاء طريقة $ application () يدويًا؟ في الواقع ، لدى AngularJS شرط واضح للغاية لذلك ، أنه من المسؤول فقط عن الاستجابة تلقائيًا للتغييرات التي تحدث في سياق AngularJS (أي التغييرات على النماذج التي تحدث في طريقة تطبيق $ ()). هذه هي الطريقة التي يقوم بها توجيه AngularJS المدمج ، لذلك ستنعكس أي تغييرات نموذج في العرض. ومع ذلك ، إذا قمت بتعديل النموذج في أي مكان خارج سياق AngularJS ، فأنت بحاجة إلى إخطار AngularJS عن طريق الاتصال بتطبيق $ () يدويًا. إنه مثل إخبار AngularJS بأنك قمت بتعديل بعض النماذج وآمل أن تساعدك AngularJs على تشغيل المراقبين على الاستجابة بشكل صحيح.
على سبيل المثال ، إذا كنت تستخدم setTimeOut () في JavaScript لتحديث نموذج النطاق ، فليس لدى AngularJS أي طريقة لمعرفة ما قمت بتغييره. في هذه الحالة ، تقع على عاتقك مسؤولية الاتصال $ Apply () ، وتشغيل حلقة $ Digest عن طريق الاتصال بها. وبالمثل ، إذا كان لديك توجيه لتعيين مستمع حدث DOM وتعديل بعض النماذج في هذا المستمع ، فيجب عليك أيضًا الاتصال بـ $ application () لضمان انعكاس التغييرات بشكل صحيح في العرض.
دعونا نلقي نظرة على مثال. انضم إلى لديك صفحة بمجرد تحميل الصفحة ، فأنت تريد عرض رسالة بعد ثانيتين. قد يبدو تنفيذك هكذا:
HTML:
<body ng-app = "myapp"> <div ng-controller = "messageController"> رسالة تأخير: {{message}} </div> </body>جافا سكريبت:
/ * ماذا يحدث بدون تطبيق $ () */ angular.module ('myapp' ، []). وحدة التحكم ('messageController' ، function ($ scope) {$ scope.getMessage = function () {setTimeOut (function () {$ scope.message = 'regled بعد 3 ثوانٍ ؛ } $ scope.getMessage () ؛من خلال تشغيل هذا المثال ، سترى أنه بعد ثانيتين ، تُظهر وحدة التحكم النموذج المحدث ، ومع ذلك ، لم يتم تحديث العرض. ربما تعرف بالفعل السبب ، وهذا هو ، لقد نسينا استدعاء طريقة $ application (). لذلك ، نحتاج إلى تعديل getMessage () على النحو التالي:
/ * ماذا يحدث مع $ تطبيق */Angular.module ('myapp' ، []). وحدة التحكم ('messageController' ، function ($ scope) {$ scope.getMessage = function () {setTimeOut (function () {$ scop $ scope.message) ؛إذا قمت بتشغيل المثال أعلاه ، فسترى أنه سيتم أيضًا تحديث العرض بعد ثانيتين. التغيير الوحيد هو أن الكود الخاص بنا يتم الآن لفه إلى نطاق $. $ application () ، والذي سيؤدي تلقائيًا إلى تشغيل $ rootscope. $ digest () ، بحيث يتم تشغيل المراقبين لتحديث العرض.
ملاحظة: بالمناسبة ، يجب عليك استخدام خدمة Timeout $ بدلاً من SetTimeOut () ، لأن الأول سيتصل بـ $ Apply () من أجلك ، لذلك لا تحتاج إلى الاتصال بها يدويًا.
لاحظ أيضًا أنه في الكود أعلاه ، يمكنك أيضًا الاتصال يدويًا $ application () بدون معلمات بعد تعديل النموذج ، تمامًا مثل ما يلي:
$ scope.getMessage = function () {setTimeOut (function () {$ scope.message = 'fetched بعد ثانيتين' ؛ console.log ('message:' + $ scope.message) ؛ $ scope. $ application () ؛ // هذا يؤدي إلى $} ، 2000) ؛ } ؛يستخدم الرمز أعلاه النموذج الثاني من $ application () ، أي النموذج بدون معلمات. من المهم أن تتذكر أنه يجب عليك دائمًا استخدام طريقة تطبيق $ () التي تأخذ وظيفة كمعلمة. هذا لأنه عندما تنقل وظيفة إلى $ application () ، سيتم لف الوظيفة في محاولة ... catch block ، لذلك بمجرد حدوث استثناء ، ستتم معالجة الاستثناء من خلال خدمة $ stiventHandler.
حالة استخدام $ application () كما يلي:
• يمكنك عادة الاتصال بـ $ application () بناءً على أي توجيه يوفره Angular يمكن استخدامه في العرض. جميع توجيهات NG- [الحدث] (مثل NG-Click ، NG-Kypress) سوف تستدعي $ application ().
• بالإضافة إلى ذلك ، يمكنك أيضًا الاعتماد على سلسلة من الخدمات المدمجة الزاوي للاتصال بـ $ Digest (). على سبيل المثال ، سيتم الاتصال بخدمة $ HTTP $ application () بعد اكتمال طلب XHR ويتم تشغيل قيمة إرجاع التحديث.
• كلما تعاملنا يدويًا للأحداث ، نستخدم أطراف الطرف الثالث (مثل jQuery ، Facebook API) ، أو Call SetTimeOut () ، يمكننا استخدام وظيفة $ application () لإحداث حلقة $ digest $.
استدعاء setTimeOut ():
<! doctype html> <html ng-app = "myapp"> <head> <title> $ scope. $ applic src = "http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"> </script> </head> <body> <div id = "div1" ng-controller = "mytext"> <viv> value = "jquery-event"> </pected> </viv> </body> </html> <script type = "text/javaScript"> var mymodule = Angular.Module ('myapp' ، []) ؛ mymodule.controller ("mytext" ، الدالة ($ scope) {$ scope.text = "place" ؛ setTimeOut (function () {$ scope.text = "value setted out out" ؛ $ scope. </script>استخدم أطر عمل الطرف الثالث (مثل jQuery ، Facebook API):
<! doctype html> <html ng-app = "myapp"> <head> <title> $ scope. $ application () use </title> <meta charset = "utf-8" src = "http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"> </script> <body> <div id = "div1" ng-controller = "mytext"> <viv> value = "jquery-event"> </pected> </viv> </body> </html> <script type = "text/javaScript"> var mymodule = Angular.Module ('myapp' ، []) ؛ mymodule.controller ("mytext" ، function ($ scope) {$ scope.text = "place" ؛}) ؛ $ (function () {$ ("#btn"). انقر فوق (function () {var $ scope = $ ("#btn").1.3. كم مرة سيتم تشغيل حلقة $ Digest؟
عند تشغيل حلقة $ Digest ، سيتم تنفيذ المراقبين للتحقق مما إذا كانت النماذج في النطاق قد تغيرت. في حالة حدوث تغيير ، سيتم تنفيذ وظيفة المستمع المقابلة. وهذا ينطوي على قضية مهمة. ماذا لو كانت وظيفة المستمع نفسها ستعدل نموذج النطاق؟ كيف سوف يتعامل AngularJS مع هذا الموقف؟
الجواب هو أن حلقة $ Digest لن يتم تشغيلها مرة واحدة فقط. بعد انتهاء الحلقة الحالية ، سيتم تنفيذ حلقة أخرى للتحقق مما إذا كانت النماذج قد تغيرت. هذا هو التحقق القذر ، والذي يتم استخدامه للتعامل مع تغييرات النموذج التي قد تحدث عند تنفيذ وظيفة المستمع. لذلك ، ستستمر حلقة $ Digest حتى لا يتغير النموذج ، أو تصل حلقة $ Digest إلى 10 مرات. لذلك ، حاول عدم تعديل النموذج في وظيفة المستمع قدر الإمكان.
ملاحظة: سيتم تشغيل حلقة $ Digest أيضًا مرتين على الأقل ، حتى لو لم يتم تغيير أي نموذج في وظيفة المستمع. كما نوقش أعلاه ، سيتم تشغيله مرة أخرى لضمان عدم تغيير النماذج.
خاتمة
أهم شيء يجب تذكره هو ما إذا كان يمكن لـ AngularJs اكتشاف تعديلاتك على النموذج. إذا كان لا يمكن اكتشافه ، فأنت بحاجة إلى الاتصال $ application () يدويًا.
إذا كان لديك أي أسئلة ، فيرجى ترك رسالة لي وسوف يرد المحرر على الجميع في الوقت المناسب. شكرا جزيلا لدعمكم لموقع wulin.com!