وحدات تحكم AngularJS مع مثال ng-Controller

⚡ ملخص ذكي

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

  • 🎯 المسؤولية الأساسية: يقوم المتحكم بتعبئة كائن النطاق ويعرض الأساليب للعرض؛ فهو لا يتلاعب بـ DOM.
  • 🔗 الأسلاك: يقوم التوجيه ng-controller بربط وحدة تحكم مسماة بعنصر، مما يمنح هذا العنصر وأبنائه إمكانية الوصول إلى نطاق وحدة التحكم.
  • 🔁 تجليد ثنائي الاتجاه: يقوم ng-model بربط حقل النموذج بخاصية النطاق، لذا فإن التعديلات في العرض تُحدّث وحدة التحكم والعكس صحيح.
  • 🧩 الأساليب: تفصل الدوال المرفقة بالنطاق أجزاءً متميزة من المنطق ويمكن استدعاؤها مباشرة من تعبيرات العرض.
  • 🏷️ صيغة وحدة التحكم: إنشاء اسم بديل لوحدة التحكم وربطها بـ this يزيل الغموض عندما تكون وحدات التحكم متداخلة داخل بعضها البعض.
  • 📁 الفصل: يؤدي نقل وحدات التحكم إلى ملف app.js مخصص إلى الحفاظ على استقلالية طبقة العرض عن طبقة المنطق.

وحدات تحكم AngularJS باستخدام ng-controller

ما هو جهاز التحكم في AngularJS؟

A مراقب في AngularJS، يستقبل التطبيق البيانات من العرض، ويعالجها، ثم يرسلها إلى العرض ليتم عرضها للمستخدم النهائي. أما وحدة التحكم، فتتضمن منطق العمل الأساسي. تستخدم وحدة التحكم نموذج البيانات، وتنفذ المعالجة المطلوبة، ثم تُمرر الناتج إلى العرض.

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

معرفة ماهية وحدة التحكم لا تزال تثير تساؤلاً واحداً: كيف تتواصل فعلياً مع واجهة المستخدم؟ سيجيب القسم التالي على هذا السؤال.

ما يفعله المتحكم من منظور Angular

فيما يلي تعريف بسيط لكيفية عمل وحدة تحكم AngularJS:

عمل وحدة تحكم AngularJS
عمل وحدة تحكم AngularJS
  • المسؤولية الأساسية لوحدة التحكم هي التحكم في البيانات التي يتم تمريرها إلى العرض. النطاق والعرض لهما اتصال في اتجاهين.
  • يمكن لخصائص العرض والأحداث استدعاء الدوال الموجودة في النطاق. يوضح المقتطف أدناه ذلك. وظيفة (نطاق $) تم تعريفها باستخدام وحدة التحكم بالإضافة إلى دالة داخلية تُرجع $scope.firstName و $scope.lastName انضم. في AngularJSالدالة المعرفة كمتغير هي طريقة.

عمل وحدة تحكم AngularJS

  • تنتقل البيانات من وحدة التحكم إلى النطاق، ثم ذهابًا وإيابًا بين النطاق والعرض.
  • يُتيح النطاق عرض النموذج للواجهة. ويمكن تعديل النموذج عبر طرق مُعرّفة في النطاق، والتي يتم تشغيلها بواسطة أحداث من الواجهة.
  • لا ينبغي استخدام وحدات التحكم لمعالجة DOM. هذه مهمة توجيهات.
  • أفضل الممارسات هي بناء وحدات التحكم على أساس الوظائف. إذا كان لديك نموذج إدخال يحتاج إلى وحدة تحكم، فأنشئ واحدة باسم "وحدة تحكم النموذج".

بعد فهم الآلية، يقوم القسم التالي بإنشاء وحدة تحكم من صفحة فارغة.

كيفية بناء وحدة تحكم أساسية في AngularJS

فيما يلي خطوات إنشاء وحدة تحكم في AngularJS.

الخطوة 1) إنشاء صفحة HTML أساسية

قبل إنشاء وحدة تحكم، يجب أن تكون صفحة HTML الأساسية جاهزة. المقتطف أدناه هو صفحة بسيطة بعنوان "تسجيل الحدث" تشير إلى Bootstrap وAngularJS.

قم ببناء وحدة تحكم أساسية في AngularJS

  1. المراجع إلى Bootstrap ورقة أنماط CSS، المستخدمة مع Bootstrap مكتبة.
  2. هذا الملف مرجع إلى مكتبة AngularJS. كل ما يتم فعله باستخدام AngularJS من الآن فصاعدًا يتم حله من خلال هذا الملف.
  3. إشارة إلى Bootstrap مكتبة تجعل بعض عناصر التحكم سريعة الاستجابة.

⚠️ تصحيح: قام البرنامج بتحميل مكتبة jQuery الأصلية وذكر أن AngularJS يعتمد عليها. هذا غير صحيح. يأتي AngularJS مزودًا بـ jqLite، وهي مجموعة فرعية مدمجة من واجهة برمجة تطبيقات jQuery، ولا يتم الترقية إلى jQuery الكاملة إلا إذا تم تحميل jQuery. قبل تمت إزالة المرجع.

الخطوة 2) التحقق من الملفات وبنية الملف

قم ببناء وحدة تحكم أساسية في AngularJS

  1. يتم تقسيم الملفات إلى مجلدين كما هو الحال في أي تطبيق ويب تقليدي: "css" لملفات أنماط CSS و "lib" لملفات CSS. Javaسيناريو الملفات.
  2. يوجد ملف bootstrap.css في مجلد css وهو الذي يمنح الموقع مظهره وشكله.
  3. angular.js هي المكتبة الرئيسية، يتم تنزيلها من موقع AngularJS ويتم الاحتفاظ بها في lib.
  4. سيحتوي ملف app.js على كود وحدات التحكم.

الخطوة 3) استخدم كود AngularJS لعرض الإخراج

الهدف هنا هو عرض الكلمات "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 التفسير:

  1. ng- التطبيق يُشير هذا إلى أن هذا العنصر هو جذر تطبيق AngularJS. السمات التي تبدأ بـ نانوغرام- هي توجيهات مضمنة. "DemoApp" هو الاسم الذي أُطلق على التطبيق.
  2. القسم يحمل نانوغرام تحكم باسم "DemoController"، مما يمنح هذا العنصر وكل ما بداخله إمكانية الوصول إلى نطاق وحدة التحكم.
  3. نانوغرام نموذج يقوم بإنشاء ربط النموذج، ويربط مربع نص اسم البرنامج التعليمي بخاصية النطاق. tutorialName.
  4. الوحدة DemoApp يتم إنشاء وحدة التحكم، وتقوم وحدة التحكم بتعيين قيمة افتراضية "AngularJS" إلى tutorialName.

⚠️ تم تطبيق التصحيحات. أعلن الإعلان الأصلي chrset="UTF 8"، وهو ليس سمة صالحة ولا اسم ترميز صالح، وقد تم تحميل AngularJS مرتين - مرة من CDN ومرة ​​من lib/angular.jsيؤدي تحميل المكتبة مرتين إلى إعادة تسجيل نظام الوحدات النمطية، مما ينتج عنه سلوك غير متوقع. شرح مصفوفة التبعية ['$scope', function($scope){…}] تمت إضافتها أيضاً، وبدونها يتعطل المتحكم بمجرد تصغير الملف.

الإخراج:

قم ببناء وحدة تحكم أساسية في AngularJS

لأن tutorialName تم تعيين القيمة "AngularJS"، وتظهر هذه القيمة في مربع النص وفي سطر النص العادي. خاصية واحدة تكفي للعرض التوضيحي؛ عادةً ما تُظهر وحدات التحكم الحقيقية سلوكًا أيضًا، وهو ما يتناوله القسم التالي.

كيفية تحديد الأساليب في وحدات تحكم AngularJS

عادةً ما يتم تعريف عدة دوال في وحدة التحكم لفصل منطق العمل. إذا كان على وحدة التحكم جمع رقمين وطرحهما.tracعند التعامل مع رقمين، ستنشئ طريقة واحدة لكل عملية.

يوضح المثال أدناه طريقة مخصصة داخل وحدة تحكم AngularJS تقوم بإرجاع سلسلة نصية.

تحديد الأساليب في وحدات تحكم 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 التفسير:

  1. يتم إرفاق دالة بكائن النطاق كعضو tName. تُعيد القيمة الحالية لـ tutorialName.
  2. يستدعي العرض الطريقة باستخدام {{tName()}}الأقواس مهمة: فبدونها، يطبع التعبير الدالة نفسها بدلاً من نتيجتها.

⚠️ تصحيح: الطريقة الأصلية تقرأ $scope.tName = function() { return $scope.tName; };تُعيد هذه الدالة نفسها، وليس اسم البرنامج التعليمي، لذا عرضت الصفحة نص الدالة بدلاً من النص. وهي الآن تُعيد $scope.tutorialName.

الإخراج:

تحديد الأساليب في وحدات تحكم AngularJS

حتى الآن، كان كل شيء موجودًا في ملف واحد. أما تطبيقات الإنتاج، فتُبقي وحدات التحكم منفصلة، ​​وهو ما سيوضحه القسم التالي.

وحدة تحكم AngularJS مع مثال ng-Controller

لقد وضع مثال "HelloWorld" أعلاه جميع الوظائف في ملف واحد. حان الوقت الآن لنقل كود وحدة التحكم إلى ملف منفصل.

الخطوة 1) أضف الكود التالي لوحدة التحكم الخاصة بك في ملف app.js.

وحدة تحكم AngularJS مع وحدة تحكم ng

angular.module('app', [])
  .controller('HelloWorldCtrl', ['$scope', function($scope) {
    $scope.message = "Hello World";
  }]);

الكود أعلاه يقوم بما يلي:

  1. يُعرّف وحدة نمطية تسمى "app" تحتوي على وحدة التحكم.
  2. يقوم بإنشاء وحدة تحكم باسم "HelloWorldCtrl" تعرض رسالة "Hello World".
  3. يستخدم كائن النطاق لتمرير المعلومات من وحدة التحكم إلى العرض، وفي هذه الحالة متغير يسمى message.

الخطوة 2) في ملف Sample.html، أضف عنصر div يحتوي على توجيه ng-controller وإشارة إلى متغير العضو messageتذكر الإشارة إلى ملف app.js، الذي يحتوي على مصدر وحدة التحكم.

وحدة تحكم AngularJS مع وحدة تحكم ng

<!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 خطأ مطبعي.

الإخراج:

وحدة تحكم AngularJS مع وحدة تحكم ng

كل مثال حتى الآن يحتوي على خصائص القراءة والكتابة مباشرة على $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، والتخزين المؤقت، وقواعد العمل

اجعل وحدات التحكم بسيطة. إذا احتاجت وحدتا تحكم إلى نفس المنطق، أو إذا كان يجب أن تبقى قيمة ما بعد الانتقال بين واجهات المستخدم، فانقلها إلى خدمة وقم بحقن تلك الخدمة حيثما دعت الحاجة. اختبار عملي هو التأكد من أن الكود سيظل منطقيًا حتى مع إغلاق الشاشة الحالية. إذا كانت الإجابة بنعم، فمكانه المناسب هو خدمة.

الأسئلة الشائعة

نعم. يقوم AngularJS بإنشاء نسخة منفصلة ونطاق منفصل لكل عنصر يحمل التوجيه. لا تشترك النسخ في أي حالة، لذا فإن أي تغيير في إحداها لا يظهر في الأخرى.

قم بتعريفه في المسار عندما ينتمي المتحكم إلى عرض كامل يتم تحميله بواسطة التوجيهاستخدم ng-controller للمكون الذي يظهر داخل الصفحة بغض النظر عن المسار الحالي. لا تقم أبدًا بتعريف كليهما، وإلا سيتم تشغيل وحدة التحكم مرتين.

استخدم خاصية المصفوفة، مع إدراج أسماء التبعيات كسلاسل نصية قبل تعريف الدالة. تعمل أدوات التصغير على إعادة تسمية وسائط الدالة، ولكنها لا تعيد تسمية القيم النصية، لذا يظل المُحقِّن قادرًا على تحديد نطاق $scope وأي خدمات بشكل صحيح.

نعم. AI يقوم المساعدون بإنشاء روابط الوحدة النمطية ووحدة التحكم والنطاق من وصف بسيط للشاشة. تحقق دائمًا من تعليق التبعية، لأن الكود المُولّد غالبًا ما يحذفه.

تقوم أدوات الذكاء الاصطناعي بإعادة كتابة تعيينات النطاق كخصائص على متغير الجهاز الظاهري الذي تم التقاطه، وتضيف البادئة إلى كل ربط عرض مطابق بالاسم المستعار. Revعرض استدعاءات $watch ومستمعي الأحداث يدويًا، لأن هذه لا تزال تتطلب كائن النطاق.

تلخيص هذه التدوينة بـ: