ما هو $scope في AngularJS؟ شرح مع مثال
⚡ ملخص ذكي
يُعدّ $Scope في AngularJS كائنًا مُدمجًا يربط وحدة التحكم بعرضها. تشرح هذه الصفحة كيفية إنشاء النطاق، ووظائف السلوك، والتسلسل الهرمي للعناصر الأبوية والفرعية، والفرق بينه وبين $rootScope، وكيفية تحديث الروابط بواسطة دورات التحديث.
ما هو النطاق $ في AngularJS؟
نطاق $ في AngularJS هو كائن مدمج يربط بشكل أساسي "وحدة التحكم" و"العرض". يمكن للمرء تحديد متغيرات الأعضاء في النطاق داخل وحدة التحكم والتي يمكن بعد ذلك الوصول إليها عن طريق العرض.
كل وحدة تحكم في AngularJS يحصل التطبيق على نسخة خاصة به من $scope من خلال حقن التبعية. أي شيء تقوم بإرفاقه بهذا الكائن يصبح مرئيًا للقالب الذي يتحكم فيه المتحكم، لذا فإن $scope يعمل كنموذج بيانات مشترك يقع بينك وبين Javaمنطق البرمجة النصية وعلامات HTML الخاصة بك.
النظر في المثال أدناه:
angular.module('app',[]).controller('HelloWorldCtrl', function($scope) { $scope.message = "Hello World" });
Code التفسير:
- اسم الوحدة هو "التطبيق"
- اسم وحدة التحكم هو "HelloWorldCtrl"
- كائن النطاق هو الكائن الرئيسي الذي يتم استخدامه لتمرير المعلومات من وحدة التحكم إلى العرض.
- تمت إضافة متغير العضو إلى كائن النطاق
⚠️ تحذير بشأن بناء الجملة: استخدم .controller() تأخذ الدالة وسيطين، اسم وحدة التحكم ودالة المصنع، لذا يلزم وضع فاصلة بينهما. 'HelloWorldCtrl' و function($scope)حذف الفاصلة يُحدث خطأً Uncaught SyntaxError قبل أن يتم إطلاق AngularJS.
لا يمثل وجود وحدة تحكم واحدة وعرض واحد سوى نصف الصورة. فالتطبيقات الحقيقية تتضمن وحدات تحكم متداخلة، وقوائم متكررة، وعناصر واجهة مستخدم معاد استخدامها، مما يعني وجود نطاقات متعددة في آن واحد.
كيفية عمل التسلسل الهرمي للنطاق والوراثة في AngularJS
يحتوي كل تطبيق AngularJS على نطاق جذر واحد فقط، وقد يحتوي على أي عدد من النطاقات الفرعية. تقوم التوجيهات بإنشاء هذه النطاقات الفرعية وربطها بعنصر DOM الذي تُزيّنه، بحيث تعكس شجرة النطاقات بنية الصفحة المعروضة.
عندما يقوم AngularJS بتقييم تعبير مثل {{siteName}}يبحث النظام أولاً عن تلك الخاصية في النطاق المرتبط بالعنصر. إذا كانت الخاصية مفقودة، ينتقل البحث إلى النطاق الأصل، ويستمر في الصعود حتى يصل إلى النطاق الجذر. Javaيعرف مطورو البرامج النصية هذا السلوك باسم الوراثة النموذجية، وترث النطاقات الفرعية من آبائها بهذه الطريقة بالضبط.
يوضح المثال أدناه كيفية تضمين وحدة تحكم داخل أخرى حتى تتمكن من مشاهدة عملية التوريث.
<div ng-app="scopeDemo"> <div ng-controller="ParentCtrl"> Parent scope value: {{siteName}} <div ng-controller="ChildCtrl"> Child reads parent value: {{siteName}} Child own value: {{lesson}} </div> </div> </div> <script type="text/javascript"> var app = angular.module("scopeDemo", []); app.controller("ParentCtrl", function($scope) { $scope.siteName = "Guru99"; }); app.controller("ChildCtrl", function($scope) { $scope.lesson = "AngularJS Scope"; }); </script>
Code التفسير:
ParentCtrlيحددsiteNameعلى نطاقها الخاص.ChildCtrlلا يحدد أبداًsiteNameومع ذلك، لا يزال العنصر div الداخلي يطبع Guru99 لأن عملية البحث تصل إلى النطاق الأصل.lessonلا يوجد إلا في نطاق العنصر الفرعي، لذلك لا يمكن للعنصر الأب قراءته.
ما هي التوجيهات التي تُنشئ نطاقًا جديدًا؟
- ng-controller: يُنشئ نطاقًا فرعيًا للعنصر الذي يتم وضعه عليه.
- ng-repeat: يقوم بإنشاء نطاق فرعي واحد لكل تكرار، ولهذا السبب يمكن أن يحتوي كل صف على قيم مختلفة لنفس التعبير.
- التوجيهات المخصصة: قد يطلبون منظارًا للأطفال، أو عزل نطاق لا يرث عمداً من نطاقه الأصلي.
- توجيهات المكونات: أي شيء مسجل لدى
.component()يتلقى المساعد دائمًا نطاقًا معزولًا.
لأن نطاقات العناصر الفرعية تقرأ من الأعلى إلى الأسفل، يتساءل المطورون غالبًا عن مكان وجود أعلى هذه السلسلة. يُطلق على هذا الكائن ذي المستوى الأعلى اسم $rootScope.
$scope مقابل $rootScope: ما الفرق؟
AngularJS $rootScope يمثل $rootScope نطاق التطبيق بأكمله. لا يمكن للتطبيق أن يحتوي إلا على $rootScope واحد، ويُستخدم كمتغير عام. كل $scope هو نطاق فرعي، و$rootScope هو النطاق الأصل في أعلى الشجرة. يقارن الجدول أدناه بين الكائنين.
| البعد | $scope | $rootScope |
|---|---|---|
| عدد الحالات لكل تطبيق | كثير، واحد لكل وحدة تحكم أو توجيه لإنشاء النطاق | واحد فقط |
| تم إنشاء الموقع الالكتروني بواسطة | توجيهات مثل ng-controller و ng-repeat | المُحقِّن أثناء بدء تشغيل التطبيق |
| وضوح | عنصرها الخاص وجميع ذريتها | كل نطاق في التطبيق |
| الاستخدام النموذجي | البيانات والسلوك لعرض واحد أو صف واحد في القائمة | القيم على مستوى التطبيق، مثل المستخدم الذي قام بتسجيل الدخول |
| الخطر الرئيسي | تصبح القيم غير قابلة للوصول إليها خارج الفرع | تضارب الأسماء والترابط الخفي، مثل المتغيرات العامة |
استخدم $rootScope باعتدال. أي بيانات تُخزّن هناك تبقى متاحة للتطبيق بأكمله ويمكن قراءتها من أي مكان، لذا فإن الخدمة المشتركة عادةً ما تكون مكانًا أكثر أمانًا للبيانات العامة. مرجع $rootScope يعرض قائمة كاملة بواجهة برمجة التطبيقات (API).
إن معرفة مكان وجود البيانات يمثل نصف المهمة. أما النصف الآخر فهو تعليم النظام كيفية الاستجابة عندما يقوم المستخدم بشيء ما.
إعداد أو إضافة سلوك في AngularJS
من أجل الرد على الأحداث أو تنفيذ نوع من الحساب/المعالجة في العرض، يجب علينا توفير السلوك للنطاق.
تتم إضافة السلوكيات إلى كائنات النطاق للرد على أحداث معينة قد يتم تشغيلها بواسطة العرض. بمجرد تعريف السلوك في وحدة التحكم، يمكن الوصول إليه عن طريق العرض.
دعونا نلقي نظرة على مثال لكيفية تحقيق ذلك.
<!DOCTYPE html> <html lang="en"> <head> <meta chrset="UTF 8"> <title>Guru99</title> </head> <body ng-app="DemoApp"> <h1> Guru99 Global Event</h1> <script src="https://code.angularjs.org/1.6.9/angular.js"></script> <div ng-controller="DemoController"> {{fullName("Guru","99")}} </div> <script type="text/javascript"> var app = angular.module("DemoApp", []); app.controller("DemoController", function($scope) { $scope.fullName=function(firstName,lastname){ return firstName + lastname; } } ); </script> </body> </html>
Code التفسير:
- نحن نقوم بإنشاء سلوك يسمى "الاسم الكامل". هذا السلوك عبارة عن دالة تقبل معلمتين (الاسم الأول واسم العائلة).
- يقوم السلوك بعد ذلك بإرجاع تسلسل هاتين المعلمتين.
- في العرض، نستدعي السلوك ونمرر قيمتين من "Guru"" و "99" والتي يتم تمريرها كمعاملات للسلوك.
إذا تم تنفيذ الأمر بنجاح، سيتم عرض الإخراج التالي عند تشغيل الكود الخاص بك في المتصفح.
الإخراج:
سترى في المتصفح سلسلة من قيم كل من Guru و99 التي تم تمريرها إلى السلوك في مراقب .
يتم تحديث الروابط مثل الرابط المذكور أعلاه تلقائيًا، والآلية التي تجعل ذلك يحدث تستحق الفهم قبل أن يصبح التطبيق كبيرًا.
لماذا يُعدّ مراقبو النطاق ودورة التلخيص مهمين؟
يحافظ AngularJS على توافق العرض مع النطاق من خلال فحص التغييرات بدلاً من أحداث التغيير. وتُشغّل ثلاث واجهات برمجة تطبيقات للنطاق هذه العملية:
- $watch: يسجل مستمعًا لتعبير معين. عمليات الاستيفاء مثل
{{fullName}}قم بتسجيل المتابعين نيابةً عنك أثناء ربط القالب. - $apply: يدخل هذا الأمر سياق تنفيذ AngularJS، ويُقيّم الكود الخاص بك، ثم يُفعّل عملية التلخيص. ولا يُستخدم إلا داخل دوال رد الاتصال الخاصة بالأحداث المخصصة أو دوال رد الاتصال الخاصة بمكتبات الطرف الثالث، لأن التوجيهات المدمجة تستدعيه بالفعل.
- ملخص: يقوم بفحص كل مراقب على $rootScope وأبنائه، ويقارن القيمة الحالية بالقيمة السابقة، ويكرر ذلك حتى يتوقف النموذج عن التغيير.
نظرًا لأن عملية التلخيص قد تُنفذ عدة دورات، يجب أن تظل تعابير المراقبة غير مكلفة. تجنب الوصول إلى DOM داخلها، لأن قراءة DOM أبطأ بكثير من قراءة... Javaخاصية البرنامج النصي.
يؤثر عمق المراقبة أيضاً على التكلفة. وتُعد المراقبة بالمرجع هي الأسرع، ولا تُلاحظ إلا عند استبدال القيمة بالكامل. $watchCollection تُلاحظ هذه العملية العناصر المضافة أو المحذوفة أو المعاد ترتيبها داخل مصفوفة أو كائن. تتطلب المراقبة حسب القيمة المرور عبر بنية متداخلة في كل عملية تجزئة، وهي الخيار الأكثر تكلفة، لذا يُنصح باللجوء إليها في النهاية.




