angularjs - services - timeout angular




"هذا" مقابل نطاق $ في وحدات التحكم AngularJS (5)

في قسم "إنشاء المكونات" في الصفحة الرئيسية ل AngularJS ، يوجد هذا المثال:

controller: function($scope, $element) {
  var panes = $scope.panes = [];
  $scope.select = function(pane) {
    angular.forEach(panes, function(pane) {
      pane.selected = false;
    });
    pane.selected = true;
  }
  this.addPane = function(pane) {
    if (panes.length == 0) $scope.select(pane);
    panes.push(pane);
  }
}

لاحظ كيف تتم إضافة طريقة select إلى $scope ، ولكن يتم إضافة أسلوب addPane إلى this . إذا قمت بتغييره إلى $scope.addPane ، $scope.addPane الكود.

تقول الوثائق أن هناك في الواقع فرقا ، لكنه لا يذكر ما هو الفرق:

سمحت الإصدارات السابقة من Angular (ما قبل 1.0 RC) باستخدام this التبادل باستخدام طريقة $scope ، ولكن لم يعد هذا هو الحال. داخل من الأساليب المحددة في نطاق this والنطاق $scope قابلة للتبادل (الزاوي يحدد this إلى $scope ) ، ولكن ليس داخل منشئ وحدة التحكم الخاصة بك.

كيف يعمل this $scope في أجهزة التحكم AngularJS؟


"كيف يعمل this $scope في أجهزة التحكم AngularJS؟"

إجابة مختصرة :

  • this
    • عندما يتم استدعاء الدالة منشئ وحدة تحكم ، this هي وحدة التحكم.
    • عندما يتم استدعاء دالة محددة على كائن $scope ، this هو "النطاق قيد التنفيذ عندما تم استدعاء الدالة". قد يكون هذا (أو قد لا يكون!) هو $scope الذي يتم تعريف الدالة عليه. لذلك ، داخل الوظيفة ، قد لا يكون this $scope هو نفسه.
  • $scope
    • لدى كل وحدة تحكم كائن $scope مقترن.
    • تكون وظيفة وحدة التحكم (منشئ) مسؤولة عن تعيين خصائص النموذج والوظائف / السلوك على $scope المرتبط به.
    • يمكن فقط الوصول إلى الطرق المحددة في كائن $scope (وكائنات نطاق الأصل ، إذا كان هناك ميراث نموذجي) من HTML / view. على سبيل المثال ، من ng-click ، filters ، إلخ.

إجابة طويلة :

وظيفة التحكم هي دالة منشئ JavaScript. عند تنفيذ وظيفة المنشئ (على سبيل المثال ، عندما يتم تحميل عرض) ، يتم تعيين this (أي "سياق الدالة") إلى كائن وحدة التحكم. حتى في وظيفة منشئ تحكم "علامات التبويب" ، عندما يتم إنشاء وظيفة addPane

this.addPane = function(pane) { ... }

يتم إنشاؤه على كائن وحدة التحكم ، وليس على نطاق $. لا يمكن أن ترى المشاهدات الدالة addPane - فهي لا تملك سوى الوصول إلى الوظائف المحددة في نطاق $. بمعنى آخر ، لن يعمل هذا في HTML:

<a ng-click="addPane(newPane)">won't work</a>

بعد تنفيذ وظيفة منشئ تحكم "علامات التبويب" ، لدينا ما يلي:

يشير الخط الأسود المتقطع إلى الوراثة النموذجية - وهو نطاق معزول يورث نموذجيًا من Scope . (لا ترث بشكل نموذجي من النطاق في الواقع حيث تم مصادفة التوجيه في HTML.)

الآن ، تريد وظيفة ارتباط توجيه جزء الاتصال مع توجيه علامات التبويب (مما يعني أنه يجب أن يؤثر على علامات التبويب في عزل نطاق $ بطريقة ما). يمكن استخدام الأحداث ، لكن هناك آلية أخرى تتمثل في جعل توجيه الجزء require جهاز تحكم علامات التبويب. (يبدو أنه لا توجد آلية لتوجيه الجزء require علامات التبويب نطاق $.)

لذلك ، يطرح هذا السؤال: إذا كان لدينا فقط إمكانية الوصول إلى وحدة تحكم علامات التبويب ، كيف يمكننا الوصول إلى علامات التبويب عزل نطاق $ (وهو ما نريده حقًا)؟

حسنا ، الخط المنقط باللون الأحمر هو الحل. يمنح "نطاق" وظيفة addPane () (أنا أشير إلى نطاق / إغلاق وظيفة جافا سكريبت هنا) وظيفة الوصول إلى علامات التبويب التي تعزل نطاق $. أي ، addPane () لديه حق الوصول إلى "علامات التبويب IsolateScope" في الرسم البياني أعلاه بسبب إغلاق الذي تم إنشاؤه عند تعريف addPane (). (إذا عمدنا بدلاً من ذلك إلى تعريف addPane () على كائن نطاق $ tabs ، فلن يتمكن التوجيه الجزئي من الوصول إلى هذه الوظيفة ، ومن ثم لن يكون لديه أي سبيل للتواصل مع علامات التبويب نطاق $.)

للإجابة على الجزء الآخر من سؤالك: how does $scope work in controllers? :

ضمن الدالات المعرّفة على نطاق $ ، يتم تعيين this على "نطاق $ في الواقع حيث / عندما تم استدعاء الدالة". لنفترض أن لدينا HTML التالي:

<div ng-controller="ParentCtrl">
   <a ng-click="logThisAndScope()">log "this" and $scope</a> - parent scope
   <div ng-controller="ChildCtrl">
      <a ng-click="logThisAndScope()">log "this" and $scope</a> - child scope
   </div>
</div>

و ParentCtrl ( ParentCtrl ) لديها

$scope.logThisAndScope = function() {
    console.log(this, $scope)
}

سيظهر النقر فوق الارتباط الأول أن this $scope ParentCtrl ، حيث أن " النطاق قيد التنفيذ عندما تم استدعاء الدالة " هو النطاق المقترن بـ ParentCtrl .

سيؤدي النقر فوق الارتباط الثاني إلى إظهار this ، ولن يكون $scope ChildCtrl ، نظرًا لأن " النطاق قيد التنفيذ عندما تم استدعاء الدالة " هو النطاق المقترن بـ ChildCtrl . هنا ، تم ضبط this $scope ChildCtrl . داخل الطريقة ، لا يزال $scope ParentCtrl $.

Fiddle

أحاول عدم استخدام this داخل دالة محددة على نطاق $ ، حيث يصبح مربكًا نطاق $ يتأثر ، لا سيما بالنظر إلى أن ng-repeat و ng-include و ng-switch والتوجيهات يمكنها إنشاء نطاقات الطفل الخاصة بهم .


سمحت الإصدارات السابقة من Angular (ما قبل 1.0 RC) باستخدام هذا التبادل باستخدام طريقة نطاق $ ، ولكن لم يعد هذا هو الحال. داخل من الأساليب المحددة في نطاق هذا والنطاق $ قابلة للتبادل (الزاوي يحدد هذا إلى نطاق دولار) ، ولكن ليس داخل منشئ وحدة التحكم الخاصة بك.

لإعادة هذا السلوك (هل يعرف أحد لماذا تم تغييره؟) يمكنك إضافة:

return angular.extend($scope, this);

في نهاية وظيفة وحدة التحكم الخاصة بك (بشرط أن يتم حقن نطاق $ لوظيفة التحكم هذه).

هذا له تأثير جيد للوصول إلى نطاق الأصل عبر كائن وحدة التحكم التي يمكنك الحصول عليها في الطفل require: '^myParentDirective'


السبب 'addPane' تم تعيينه لهذا بسبب توجيه <pane> .

require: '^tabs' توجيه pane require: '^tabs' ، التي تضع كائن وحدة تحكم علامات التبويب من توجيه أصل ، في وظيفة الارتباط.

يتم تعيين addPane إلى this بحيث يمكن أن تراه وظيفة ارتباط pane . ثم في الوظيفة "ارتباط pane ، addPane الوظيفة addPane مجرد خاصية تحكم tabs ، وهي فقط tabsControllerObject.addPane. لذلك يمكن لوصلة الربط في توجيه جزء الوصول إلى كائن وحدة تحكم علامات التبويب وبالتالي الوصول إلى أسلوب addPane.

آمل أن يكون شرحي واضحًا بما يكفي .. إنه أمر يصعب تفسيره.


في هذه الدورة التدريبية ( https://www.codeschool.com/courses/shaping-up-with-angular-js ) يشرحون كيفية استخدام "هذا" والعديد من الأشياء الأخرى.

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

على سبيل المثال باستخدام وحدة التحكم الخاصة بك في طريقة العرض ، قد يكون لديك كود مثل:

    <div data-ng-controller="YourController as aliasOfYourController">

       Your first pane is {{aliasOfYourController.panes[0]}}

    </div>

نطاق $ لديه "هذا" مختلفة ثم تحكم "هذا". إذا وضعت وحدة تحكم console.log (هذا) داخل جهاز تحكم فإنه يعطيك كائن (وحدة تحكم) و. addPane () يضيف أسلوب addPane إلى كائن وحدة تحكم. لكن نطاق $ النطاق له نطاق مختلف وكل طريقة في نطاقه تحتاج إلى أن يكون accesed بواسطة $ scope.methodName (). this.methodName() داخل جهاز التحكم يعني إضافة methos داخل كائن وحدة التحكم. $scope.functionName() في HTML وداخل

$scope.functionName(){
    this.name="Name";
    //or
    $scope.myname="myname"//are same}

الصق هذا الرمز في المحرر وفتح وحدة التحكم للاطلاع ...

 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>this $sope vs controller</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.7/angular.min.js"></script>
    <script>
        var app=angular.module("myApp",[]);
app.controller("ctrlExample",function($scope){
          console.log("ctrl 'this'",this);
          //this(object) of controller different then $scope
          $scope.firstName="Andy";
          $scope.lastName="Bot";
          this.nickName="ABot";
          this.controllerMethod=function(){

            console.log("controllerMethod ",this);
          }
          $scope.show=function(){
              console.log("$scope 'this",this);
              //this of $scope
              $scope.message="Welcome User";
          }

        });
</script>
</head>
<body ng-app="myApp" >
<div ng-controller="ctrlExample">
       Comming From $SCOPE :{{firstName}}
       <br><br>
       Comming from $SCOPE:{{lastName}}
       <br><br>
       Should Come From Controller:{{nickName}}
       <p>
            Blank nickName is because nickName is attached to 
           'this' of controller.
       </p>

       <br><br>
       <button ng-click="controllerMethod()">Controller Method</button>

       <br><br>
       <button ng-click="show()">Show</button>
       <p>{{message}}</p>

   </div>

</body>
</html>




this