وحدات تحكم AngularJS مع مثال ng-Controller
⚡ ملخص ذكي
يتولى المتحكم في AngularJS إدارة منطق العمل الخاص بالشاشة. يستقبل البيانات من خلال كائن النطاق، ويعالجها، ثم يعرض النتيجة مرة أخرى للعرض، ويحتفظ بـping ترميز العرض التقديمي خالٍ من منطق التطبيق.

ما هو جهاز التحكم في AngularJS؟
A مراقب في AngularJS، يستقبل التطبيق البيانات من العرض، ويعالجها، ثم يرسلها إلى العرض ليتم عرضها للمستخدم النهائي. أما وحدة التحكم، فتتضمن منطق العمل الأساسي. تستخدم وحدة التحكم نموذج البيانات، وتنفذ المعالجة المطلوبة، ثم تُمرر الناتج إلى العرض.
⚠️ ملاحظة حول الإصدار: وصل دعم AngularJS (الإصدار 1.x) إلى نهايته في 31 ديسمبر 2021، ولم يعد يتلقى أي تحديثات أمنية. لا تزال المفاهيم المذكورة أدناه سارية على التطبيقات القديمة؛ أما في Angular الحديث، فيؤدي فئة المكون الدور نفسه بدلاً من وحدة التحكم.
معرفة ماهية وحدة التحكم لا تزال تثير تساؤلاً واحداً: كيف تتواصل فعلياً مع واجهة المستخدم؟ سيجيب القسم التالي على هذا السؤال.
ما يفعله المتحكم من منظور Angular
فيما يلي تعريف بسيط لكيفية عمل وحدة تحكم AngularJS:

- المسؤولية الأساسية لوحدة التحكم هي التحكم في البيانات التي يتم تمريرها إلى العرض. النطاق والعرض لهما اتصال في اتجاهين.
- يمكن لخصائص العرض والأحداث استدعاء الدوال الموجودة في النطاق. يوضح المقتطف أدناه ذلك. وظيفة (نطاق $) تم تعريفها باستخدام وحدة التحكم بالإضافة إلى دالة داخلية تُرجع
$scope.firstNameو$scope.lastNameانضم. في AngularJSالدالة المعرفة كمتغير هي طريقة.
- تنتقل البيانات من وحدة التحكم إلى النطاق، ثم ذهابًا وإيابًا بين النطاق والعرض.
- يُتيح النطاق عرض النموذج للواجهة. ويمكن تعديل النموذج عبر طرق مُعرّفة في النطاق، والتي يتم تشغيلها بواسطة أحداث من الواجهة.
- لا ينبغي استخدام وحدات التحكم لمعالجة DOM. هذه مهمة توجيهات.
- أفضل الممارسات هي بناء وحدات التحكم على أساس الوظائف. إذا كان لديك نموذج إدخال يحتاج إلى وحدة تحكم، فأنشئ واحدة باسم "وحدة تحكم النموذج".
بعد فهم الآلية، يقوم القسم التالي بإنشاء وحدة تحكم من صفحة فارغة.
كيفية بناء وحدة تحكم أساسية في AngularJS
فيما يلي خطوات إنشاء وحدة تحكم في AngularJS.
الخطوة 1) إنشاء صفحة HTML أساسية
قبل إنشاء وحدة تحكم، يجب أن تكون صفحة HTML الأساسية جاهزة. المقتطف أدناه هو صفحة بسيطة بعنوان "تسجيل الحدث" تشير إلى Bootstrap وAngularJS.
- المراجع إلى Bootstrap ورقة أنماط CSS، المستخدمة مع Bootstrap مكتبة.
- هذا الملف مرجع إلى مكتبة AngularJS. كل ما يتم فعله باستخدام AngularJS من الآن فصاعدًا يتم حله من خلال هذا الملف.
- إشارة إلى Bootstrap مكتبة تجعل بعض عناصر التحكم سريعة الاستجابة.
⚠️ تصحيح: قام البرنامج بتحميل مكتبة jQuery الأصلية وذكر أن AngularJS يعتمد عليها. هذا غير صحيح. يأتي AngularJS مزودًا بـ jqLite، وهي مجموعة فرعية مدمجة من واجهة برمجة تطبيقات jQuery، ولا يتم الترقية إلى jQuery الكاملة إلا إذا تم تحميل jQuery. قبل تمت إزالة المرجع.
الخطوة 2) التحقق من الملفات وبنية الملف
- يتم تقسيم الملفات إلى مجلدين كما هو الحال في أي تطبيق ويب تقليدي: "css" لملفات أنماط CSS و "lib" لملفات CSS. Javaسيناريو الملفات.
- يوجد ملف bootstrap.css في مجلد css وهو الذي يمنح الموقع مظهره وشكله.
- angular.js هي المكتبة الرئيسية، يتم تنزيلها من موقع AngularJS ويتم الاحتفاظ بها في lib.
- سيحتوي ملف app.js على كود وحدات التحكم.
الخطوة 3) استخدم كود AngularJS لعرض الإخراج
الهدف هنا هو عرض الكلمات "AngularJS" كنص عادي وداخل مربع نص عند فتح الصفحة في المتصفح.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Event Registration</title> <link rel="stylesheet" href="css/bootstrap.css"> </head> <body> <h1> Guru99 Global Event</h1> <div ng-app="DemoApp" ng-controller="DemoController"> Tutorial Name : <input type="text" ng-model="tutorialName"><br> This tutorial is {{tutorialName}} </div> <script src="lib/angular.js"></script> <script> var app = angular.module('DemoApp', []); app.controller('DemoController', ['$scope', function($scope) { $scope.tutorialName = "AngularJS"; }]); </script> </body> </html>
Code التفسير:
- ng- التطبيق يُشير هذا إلى أن هذا العنصر هو جذر تطبيق AngularJS. السمات التي تبدأ بـ نانوغرام- هي توجيهات مضمنة. "DemoApp" هو الاسم الذي أُطلق على التطبيق.
- القسم يحمل نانوغرام تحكم باسم "DemoController"، مما يمنح هذا العنصر وكل ما بداخله إمكانية الوصول إلى نطاق وحدة التحكم.
- نانوغرام نموذج يقوم بإنشاء ربط النموذج، ويربط مربع نص اسم البرنامج التعليمي بخاصية النطاق.
tutorialName. - الوحدة
DemoAppيتم إنشاء وحدة التحكم، وتقوم وحدة التحكم بتعيين قيمة افتراضية "AngularJS" إلىtutorialName.
⚠️ تم تطبيق التصحيحات. أعلن الإعلان الأصلي chrset="UTF 8"، وهو ليس سمة صالحة ولا اسم ترميز صالح، وقد تم تحميل AngularJS مرتين - مرة من CDN ومرة من lib/angular.jsيؤدي تحميل المكتبة مرتين إلى إعادة تسجيل نظام الوحدات النمطية، مما ينتج عنه سلوك غير متوقع. شرح مصفوفة التبعية ['$scope', function($scope){…}] تمت إضافتها أيضاً، وبدونها يتعطل المتحكم بمجرد تصغير الملف.
الإخراج:
لأن tutorialName تم تعيين القيمة "AngularJS"، وتظهر هذه القيمة في مربع النص وفي سطر النص العادي. خاصية واحدة تكفي للعرض التوضيحي؛ عادةً ما تُظهر وحدات التحكم الحقيقية سلوكًا أيضًا، وهو ما يتناوله القسم التالي.
كيفية تحديد الأساليب في وحدات تحكم AngularJS
عادةً ما يتم تعريف عدة دوال في وحدة التحكم لفصل منطق العمل. إذا كان على وحدة التحكم جمع رقمين وطرحهما.tracعند التعامل مع رقمين، ستنشئ طريقة واحدة لكل عملية.
يوضح المثال أدناه طريقة مخصصة داخل وحدة تحكم AngularJS تقوم بإرجاع سلسلة نصية.
<!-- The head and library references are unchanged from Step 3 --> <div ng-app="DemoApp" ng-controller="DemoController"> Tutorial Name : <input type="text" ng-model="tutorialName"><br> This tutorial is {{tName()}} </div> <script> var app = angular.module('DemoApp', []); app.controller('DemoController', ['$scope', function($scope) { $scope.tutorialName = "AngularJS"; // A method on the scope, callable from the view as tName() $scope.tName = function() { return $scope.tutorialName; }; }]); </script>
Code التفسير:
- يتم إرفاق دالة بكائن النطاق كعضو
tName. تُعيد القيمة الحالية لـtutorialName. - يستدعي العرض الطريقة باستخدام
{{tName()}}الأقواس مهمة: فبدونها، يطبع التعبير الدالة نفسها بدلاً من نتيجتها.
⚠️ تصحيح: الطريقة الأصلية تقرأ $scope.tName = function() { return $scope.tName; };تُعيد هذه الدالة نفسها، وليس اسم البرنامج التعليمي، لذا عرضت الصفحة نص الدالة بدلاً من النص. وهي الآن تُعيد $scope.tutorialName.
الإخراج:
حتى الآن، كان كل شيء موجودًا في ملف واحد. أما تطبيقات الإنتاج، فتُبقي وحدات التحكم منفصلة، وهو ما سيوضحه القسم التالي.
وحدة تحكم AngularJS مع مثال ng-Controller
لقد وضع مثال "HelloWorld" أعلاه جميع الوظائف في ملف واحد. حان الوقت الآن لنقل كود وحدة التحكم إلى ملف منفصل.
الخطوة 1) أضف الكود التالي لوحدة التحكم الخاصة بك في ملف app.js.
angular.module('app', []) .controller('HelloWorldCtrl', ['$scope', function($scope) { $scope.message = "Hello World"; }]);
الكود أعلاه يقوم بما يلي:
- يُعرّف وحدة نمطية تسمى "app" تحتوي على وحدة التحكم.
- يقوم بإنشاء وحدة تحكم باسم "HelloWorldCtrl" تعرض رسالة "Hello World".
- يستخدم كائن النطاق لتمرير المعلومات من وحدة التحكم إلى العرض، وفي هذه الحالة متغير يسمى
message.
الخطوة 2) في ملف Sample.html، أضف عنصر div يحتوي على توجيه ng-controller وإشارة إلى متغير العضو messageتذكر الإشارة إلى ملف app.js، الذي يحتوي على مصدر وحدة التحكم.
<!DOCTYPE html> <html ng-app="app"> <head> <meta charset="UTF-8"> <title>Event Registration</title> <link rel="stylesheet" href="css/bootstrap.css"> </head> <body> <h1> Guru99 Global Event</h1> <div class="container"> <div ng-controller="HelloWorldCtrl">{{message}}</div> </div> <script src="lib/angular.js"></script> <script src="app.js"></script> </body> </html>
⚠️ تصحيح: يجب تحميل ملف app.js بعد angular.js، لأنه يستدعي angular.moduleحمّلت النسخة الأصلية المكتبة مرتين وحملت نفس البيانات. chrset خطأ مطبعي.
الإخراج:
كل مثال حتى الآن يحتوي على خصائص القراءة والكتابة مباشرة على $scopeيتناول القسم أدناه البديل الذي يوصي به فريق AngularJS بدلاً من ذلك.
كيفية استخدام صيغة controllerAs في AngularJS
الارتباط مباشرة بـ $scope يعمل، لكنه يصبح غامضًا بمجرد تداخل وحدات التحكم. تعبير عرض مثل {{name}} لا يُعطي أي دليل على وحدة التحكم التي تملكها nameولأن نطاقات الأبناء ترث من نطاقات الآباء بشكل نموذجي، فإن وحدة التحكم المتداخلة التي تكتب إلى عنصر بدائي موروث تنشئ نسخة ظل خاصة بها بصمت. controllerAs يحل بناء الجملة كلا المشكلتين من خلال إعطاء كل وحدة تحكم اسمًا مستعارًا.
الخطوة 1) قم بتسمية وحدة التحكم في العرض باستخدام as ثم قم بإضافة الكلمة المفتاحية إلى كل ربط باستخدام هذا الاسم المستعار.
الخطوة 2) داخل وحدة التحكم، قم بإرفاق الخصائص بـ this بدلا من $scope.
<div ng-controller="DemoController as demo"> Tutorial Name : <input type="text" ng-model="demo.tutorialName"> This tutorial is {{demo.tutorialName}} </div> <script> app.controller('DemoController', function() { // 'vm' is captured so nested functions keep the right reference var vm = this; vm.tutorialName = "AngularJS"; vm.tName = function() { return vm.tutorialName; }; }); </script>
تترتب على ذلك ثلاث مكاسب. تصبح الروابط موثقة ذاتيًا، لأن demo.tutorialName يُحدد مالكه. تتوقف وحدات التحكم المتداخلة عن التصادم، نظرًا لأن الأصل مُستعار outer وطفل يحمل اسمًا مستعارًا inner كلاهما يمكن أن يكشف nameكما يتم ربط القيم من خلال كائن بدلاً من عنصر أولي مجرد، لتجنب ذلك.ping الفخ الذي لا يصل فيه التعديل في الابن إلى الأصل.
؟؟؟؟ تلميح: إنها تقوم بالتسجيل this إلى متغير مثل vm في أعلى وحدة التحكم. داخل دالة رد نداء، this يشير إلى شيء آخر تمامًا، ويحافظ المرجع الملتقط على الربط بشكل صحيح.
يُعد اختيار أسلوب الربط قرارًا، أما تحديد ما يجب تضمينه في وحدة التحكم فهو قرار آخر، والمقارنة أدناه توضح هذا الفرق.
المتحكم مقابل الخدمة في AngularJS
كثيرًا ما يُحمّل المبتدئون وحدة التحكم بمهامٍ تُناسب الخدمة. ويكمن الفرق في مدة صلاحيتها وإمكانية إعادة استخدامها: فوحدة التحكم موجودة فقط طالما أن عرضها مُتاح على الشاشة، بينما الخدمة عبارة عن عنصر فريد (singleton) يبقى موجودًا طوال فترة تشغيل التطبيق.
| البعد | مراقب | الخدمة |
|---|---|---|
| حياة | تم إنشاؤها وتدميرها وفقًا للرؤية | نسخة واحدة للتطبيق بأكمله |
| الهدف | قم بإعداد البيانات لعرض واحد | المنطق المشترك، والحالة، واستدعاءات الخادم |
| قابلة لإعادة الاستخدام | لا، مرتبط بمنظرها | نعم، يمكن حقنها في أي مكان |
| يحتفظ بالحالة بين العروض | لا، يتم فقدان الحالة أثناء التنقل | نعم، الحالة مستمرة |
| المحتوى النموذجي | خصائص النطاق وطرق العرض | استدعاءات HTTP، والتخزين المؤقت، وقواعد العمل |
اجعل وحدات التحكم بسيطة. إذا احتاجت وحدتا تحكم إلى نفس المنطق، أو إذا كان يجب أن تبقى قيمة ما بعد الانتقال بين واجهات المستخدم، فانقلها إلى خدمة وقم بحقن تلك الخدمة حيثما دعت الحاجة. اختبار عملي هو التأكد من أن الكود سيظل منطقيًا حتى مع إغلاق الشاشة الحالية. إذا كانت الإجابة بنعم، فمكانه المناسب هو خدمة.










