javascript شرح - كيف يعمل ربط البيانات في AngularJS؟




download data (12)

تنشئ Angular.js مراقباً لكل نموذج ننشئه في العرض. كلما تم تغيير نموذج ، يتم ربط فئة "ng-dirty" بالنموذج ، لذلك سيراقب المراقب جميع الموديلات التي تحتوي على فئة "ng-dirty" وتحديث قيمها في وحدة التحكم والعكس.

كيف يعمل ربط البيانات في إطار AngularJS ؟

لم أجد تفاصيل فنية على موقعهم . من الواضح أكثر أو أقل كيف يعمل عندما يتم نشر البيانات من العرض إلى النموذج. ولكن كيف يتتبع AngularJS تغييرات خصائص النموذج دون الحاصلين على الجوائز؟

لقد وجدت أن هناك مراقبي جافا سكريبت يمكنهم القيام بهذا العمل. ولكنها غير معتمدة في Internet Explorer 6 و Internet Explorer 7 . إذن كيف يعرف AngularJS أنني غيرت على سبيل المثال ما يلي وعكست هذا التغيير في طريقة العرض؟

myobject.myproperty="new value";

AngularJs يدعم ربط البيانات ثنائية الاتجاه .
يعني أنك تستطيع الوصول إلى البيانات View -> Controller & Controller -> View

على سبيل المثال

1)

// If $scope have some value in Controller. 
$scope.name = "Peter";

// HTML
<div> {{ name }} </div>

O / P

Peter

يمكنك ربط البيانات ng-model مثل: -
2)

<input ng-model="name" />

<div> {{ name }} </div>

هنا في المثال أعلاه ، ما الذي سيعطيه مستخدم المدخلات ، سيكون مرئيًا في العلامة <div> .

إذا كنت تريد ربط الإدخال من html إلى وحدة تحكم: -
3)

<form name="myForm" ng-submit="registration()">
   <label> Name </lbel>
   <input ng-model="name" />
</form>

هنا إذا كنت تريد استخدام name الإدخال في وحدة التحكم ،

$scope.name = {};

$scope.registration = function() {
   console.log("You will get the name here ", $scope.name);
};

ng-model ربط العرض وعرضه في التعبير {{ }} .
ng-model هي البيانات التي يتم عرضها للمستخدم في العرض والتي يتفاعل معها المستخدم.
لذلك فمن السهل ربط البيانات في AngularJs.


بواسطة dirty فحص كائن $scope

يحافظ الزاوي على مجموعة بسيطة من المراقبين في كائنات $scope . إذا قمت بفحص أي $scope فسوف تجد أنه يحتوي على array تسمى $$watchers .

كل مراقب هو object يحتوي على أشياء أخرى

  1. تعبير يراقبه المراقب. قد يكون هذا مجرد اسم attribute أو شيء أكثر تعقيدًا.
  2. آخر قيمة معروفة للتعبير. يمكن التحقق من هذا مقابل القيمة المحسوبة الحالية للتعبير. إذا اختلفت القيم ، سيشغل المشاهد الوظيفة ويضع علامة على $scope كمساخ.
  3. وظيفة سيتم تنفيذها إذا كان المراقِب متسخًا.

كيف يتم تحديد مراقبي

هناك العديد من الطرق المختلفة لتعريف مراقب في AngularJS.

  • يمكنك صراحة $watch attribute على $scope .

    $scope.$watch('person.username', validateUnique);
    
  • يمكنك وضع {{}} استيفاء في القالب الخاص بك (سيتم إنشاء مراقب لك على $scope الحالي).

    <p>username: {{person.username}}</p>
    
  • يمكنك أن تطلب توجيهًا مثل ng-model لتحديد المراقب لك.

    <input ng-model="person.username" />
    

تتحقق دورة $digest جميع المراقبين مقابل قيمتها الأخيرة

عندما نتفاعل مع AngularJS من خلال القنوات العادية (ng-model، ng-repeat، etc) سيتم تشغيل دورة الخلاصة بواسطة التوجيه.

تعتبر دورة الموجز عبارة عن اجتياز عمق عام واحد لكل $scope وكل أطفاله . بالنسبة إلى كل object $scope ، فإننا نكرر array $$watchers ونقيم جميع التعبيرات. إذا كانت قيمة التعبير الجديدة مختلفة عن آخر قيمة معروفة ، يتم استدعاء وظيفة المراقب. قد تعيد هذه الوظيفة تجميع جزء من DOM ، أو إعادة حساب قيمة على $scope ، أو تشغيل request AJAX ، أو أي شيء تحتاجه للقيام به.

يتم اجتياز كل نطاق وكل تقييم للساعة يتم تقييمه والتحقق منه مقابل القيمة الأخيرة.

إذا تم تشغيل أحد المراقبين ، فسيكون $scope سيئًا

إذا تم تشغيل أحد المراقبين ، فإن التطبيق يعرف أن شيئًا ما قد تغير ، وأن $scope يتم وضعه على أنه سيئ.

يمكن لوظائف مراقب تغيير سمات أخرى على $scope أو على $scope الأصل. إذا تم تشغيل وظيفة $watcher واحدة ، فلا يمكننا ضمان أن $scope s الآخر الخاص بنا لا يزال نظيفًا ، ولذا فإننا ننفذ دورة الملخص بالكامل مرة أخرى.

ويرجع ذلك إلى أن AngularJS يحتوي على ربط ثنائي الاتجاه ، لذا يمكن تمرير البيانات احتياطيًا لشجرة $scope . قد نغير قيمة على $scope أعلى تم هضمه بالفعل. ربما نغير قيمة على $rootScope .

إذا كان $digest ، فسنقوم بتنفيذ دورة $digest بالكامل مرة أخرى

نتواصل باستمرار من خلال دورة $digest حتى تصبح دورة الهضم نظيفة (جميع تعبيرات $watch لها نفس القيمة التي كانت عليها في الدورة السابقة) ، أو نصل إلى حد الملخص. بشكل افتراضي ، يتم تعيين هذا الحد على 10.

إذا وصلنا إلى حد التلخيص ، فسترفع AngularJS خطأً في وحدة التحكم:

10 $digest() iterations reached. Aborting!

يكون الخلاصة صعبة على الجهاز ولكنها سهلة على المطور

كما ترى ، في كل مرة يتغير شيء في تطبيق AngularJS ، سيتحقق AngularJS من كل مراقب في التسلسل الهرمي $scope لمعرفة كيفية الاستجابة. بالنسبة إلى مطور البرامج ، هذه هي نعمة إنتاجية هائلة ، حيث تحتاج الآن إلى كتابة أي رمز توصيل لاسلكي تقريبًا ، فلن تلاحظ AngularJS إلا إذا تغيرت القيمة ، وجعل باقي التطبيق متوافقًا مع التغيير.

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

من السهل الوصول إلى هذا الحد إذا قمت بإعادة ng-repeat على array JSON كبير على سبيل المثال. يمكنك التخفيف من هذا باستخدام ميزات مثل الربط لمرة واحدة لتجميع قالب دون إنشاء مراقبين.

كيف تتجنب إنشاء الكثير من المراقبين

في كل مرة يتفاعل فيها المستخدم مع تطبيقك ، سيتم تقييم كل مراقب واحد في تطبيقك مرة واحدة على الأقل. يتمثل جزء كبير من تحسين تطبيق AngularJS في تقليل عدد المراقبين في شجرة $scope . طريقة واحدة سهلة للقيام بذلك هي مع ملزمة مرة واحدة .

إذا كانت لديك بيانات نادرًا ما تتغير ، فيمكنك ربطها مرة واحدة فقط باستخدام بناء الجملة :: مثل:

<p>{{::person.username}}</p>

أو

<p ng-bind="::person.username"></p>

سوف يتم تشغيل الربط فقط عندما يتم تقديم القالب المحتوي على البيانات ويتم تحميل البيانات في $scope .

هذا مهم بشكل خاص عندما يكون لديك ng-repeat مع العديد من العناصر.

<div ng-repeat="person in people track by username">
  {{::person.username}}
</div>

من الواضح أنه لا يوجد فحص دوري Scope ما إذا كان هناك أي تغيير في الكائنات المرتبطة به. لا تتم مراقبة جميع الكائنات المرتبطة بالنطاق. نطاق prototypically يحافظ على مراقبي $$ . Scope لا يتكرر إلا من خلال هؤلاء $$watchers عندما يسمى $digest .

يضيف Angular مراقباً إلى مراقبي $$ لكل من هؤلاء

  1. {{التعبير}} - في النماذج (وفي أي مكان آخر يتضمن تعبيرًا) أو عندما نحدد نموذج ng.
  2. نطاق $. $ watch ('expression / function') - في JavaScript الخاص بك ، يمكننا فقط إرفاق كائن نطاق للزاوية لمشاهدة.

تأخذ وظيفة المشاهدة $ في ثلاث معايير:

  1. الأول هو وظيفة مراقب تقوم فقط بإرجاع الكائن أو يمكننا فقط إضافة تعبير.

  2. الثانية هي وظيفة المستمع والتي سيتم استدعاؤها عندما يكون هناك تغيير في الكائن. سيتم تنفيذ جميع الأمور مثل تغييرات DOM في هذه الوظيفة.

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

Scope.prototype.$watch = function(watchFn, listenerFn) {
   var watcher = {
       watchFn: watchFn,
       listenerFn: listenerFn || function() { },
       last: initWatchVal  // initWatchVal is typically undefined
   };
   this.$$watchers.push(watcher); // pushing the Watcher Object to Watchers  
};

هناك شيء مثير للاهتمام في Angular يسمى Digest Cycle. تبدأ دورة $ digest نتيجة استدعاء النطاق $. $ digest (). افترض أنك قمت بتغيير نموذج نطاق $ في وظيفة معالج من خلال توجيه ng-click. في هذه الحالة ، يقوم AngularJS تلقائيًا بتشغيل دورة $ digest عن طريق استدعاء $ digest () ، بالإضافة إلى ng-click ، ​​هناك العديد من التوجيهات / الخدمات المضمنة الأخرى التي تسمح لك بتغيير النماذج (مثل ng-model ، $ timeout ، الخ) ويبدأ تلقائيًا دورة $ digest. يبدو أن التنفيذ التقريبي لمقدار $ $ يشبه هذا.

Scope.prototype.$digest = function() {
      var dirty;
      do {
          dirty = this.$$digestOnce();
      } while (dirty);
}
Scope.prototype.$$digestOnce = function() {
   var self = this;
   var newValue, oldValue, dirty;
   _.forEach(this.$$watchers, function(watcher) {
          newValue = watcher.watchFn(self);
          oldValue = watcher.last;   // It just remembers the last value for dirty checking
          if (newValue !== oldValue) { //Dirty checking of References 
   // For Deep checking the object , code of Value     
   // based checking of Object should be implemented here
             watcher.last = newValue;
             watcher.listenerFn(newValue,
                  (oldValue === initWatchVal ? newValue : oldValue),
                   self);
          dirty = true;
          }
     });
   return dirty;
 };

إذا استخدمنا الدالة setTimeout () لـ JavaScript لتحديث نموذج نطاق ، فلن يكون لدى Angular أي طريقة لمعرفة ما قد تغيره. في هذه الحالة تقع على عاتقنا مسئولية استدعاء $ apply () يدويًا ، مما يؤدي إلى تشغيل دورة $ digest. وبالمثل ، إذا كان لديك توجيه يقوم بإعداد وحدة إصغاء حدث DOM وتغيير بعض النماذج داخل دالة المعالج ، فستحتاج إلى الاتصال بـ $ apply () لضمان سريان مفعول التغييرات. تتمثل الفكرة الكبرى لتطبيق $ في أنه يمكننا تنفيذ بعض الرموز التي لا تدرك Angular ، فقد يستمر هذا الرمز في تغيير الأشياء في النطاق. إذا قمنا بلف هذا الرمز في $ apply ، فسوف يتولى الأمر استدعاء $ digest (). تطبيق تقريبي $ apply ().

Scope.prototype.$apply = function(expr) {
       try {
         return this.$eval(expr); //Evaluating code in the context of Scope
       } finally {
         this.$digest();
       }
};

في ما يلي مثال لربط البيانات مع AngularJS ، باستخدام حقل إدخال. سأشرح لاحقا

كود HTML

<div ng-app="myApp" ng-controller="myCtrl" class="formInput">
     <input type="text" ng-model="watchInput" Placeholder="type something"/>
     <p>{{watchInput}}</p> 
</div>

AngularJS رمز

myApp = angular.module ("myApp", []);
myApp.controller("myCtrl", ["$scope", function($scope){
  //Your Controller code goes here
}]);

كما ترون في المثال أعلاه ، تستخدم AngularJS ng-model للاستماع ومشاهدة ما يحدث على عناصر HTML ، خاصة في حقول input . عندما يحدث شيء ما ، افعل شيئًا. في حالتنا ، يرتبط ng-model برأينا ، باستخدام علامة الشارب {{}} . يتم عرض أي شيء يتم كتابته داخل حقل الإدخال على الشاشة على الفور. وهذا هو جمال ربط البيانات باستخدام AngularJS في أبسط صوره.

أتمنى أن يساعدك هذا.

شاهد مثالًا Codepen هنا على Codepen


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

  2. ربط البيانات في تطبيقات Angular هو التزامن التلقائي للبيانات بين النموذج ومكونات العرض.

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


تعالج AngularJS آلية ربط البيانات بمساعدة ثلاث وظائف قوية: $watch() ، $digest() و $apply() . في معظم الأوقات ، ستستدعي AngularJS نطاق $. $ watch () ونطاق $. $ digest () ، ولكن في بعض الحالات قد تضطر إلى استدعاء هذه الوظائف يدويًا لتحديثها بقيم جديدة.

$ watch () : -

يتم استخدام هذه الوظيفة لمراقبة التغييرات في متغير على نطاق $. يقبل ثلاث معلمات: التعبير ، المستمع وكائن المساواة ، حيث يكون عنصر المستمع والمساواة معلمات اختيارية.

$ digest () -

تتكرر هذه الدالة عبر كافة الساعات الموجودة في كائن نطاق $ ، وكائنات نطاق $ التابعة الخاصة به
(إذا كان لديه أي). عندما يتكرر $ digest () على الساعات ، فإنه يتحقق مما إذا تم تغيير قيمة التعبير. إذا تغيرت القيمة ، فإن AngularJS يستدعي المستمع بقيمة جديدة وقيمة قديمة. يتم استدعاء الدالة $ digest () عندما يعتقد AngularJS أنه ضروري. على سبيل المثال ، بعد النقر على زر ، أو بعد مكالمة AJAX. قد يكون لديك بعض الحالات التي لا يقوم فيها AngularJS باستدعاء الدالة $ digest () نيابة عنك. في هذه الحالة عليك أن تسميها بنفسك.

$ apply () -

يقوم Angular بإجراء التحديثات التلقائية السحرية فقط بتغييرات الطراز الموجودة داخل سياق AngularJS. عندما تقوم بالتغيير في أي نموذج خارج السياق الزاوي (مثل أحداث DOM للمتصفح ، setTimeout ، XHR أو مكتبات الطرف الثالث) ، فأنت بحاجة إلى إعلام Angular بالتغييرات عن طريق استدعاء $ apply () يدويًا. عند انتهاء استدعاء الدالة $ () التطبيق () المكالمات AngularJS $ digest () داخليًا ، بحيث يتم تحديث كافة عمليات ربط البيانات.


شرح مع الصور:

ربط البيانات يحتاج إلى رسم الخرائط

المرجع في النطاق ليس بالضبط المرجع في القالب. عندما تقوم بربط كائنين ببيانات ، فإنك تحتاج إلى كائن ثالث يستمع إلى الآخر ويقوم بتعديل الآخر.

هنا ، عند تعديل <input> ، تلمس بيانات ref3 . وستعمل الآلية الكلاسيكية المرتبطة بالبيانات على تغيير بيانات ref4 . إذاً كيف ستنقل تعبيرات {{data}} ؟

الأحداث تؤدي إلى $ digest ()

يحافظ الزاوي على قيمة oldValue newValue لكل ارتباط. وبعد كل حدث Angular ، ستقوم حلقة $digest() الشهيرة بالتحقق من WatchList لمعرفة ما إذا تغير شيء ما. هذه الأحداث الزاويّة هي ng-click ، ng-change ، $http completed… The $digest() ستعمل طالما أن أي oldValue يختلف عن newValue .

في الصورة السابقة ، ستلاحظ أن البيانات ref1 و data-ref2 قد تغيرت.

الاستنتاجات

انها قليلا مثل البيض والدجاج. أنت لا تعرف أبدا من يبدأ ، ولكن نأمل أن يعمل في معظم الوقت كما هو متوقع.

النقطة الأخرى هي أنه يمكنك بسهولة فهم الأثر العميق لربط بسيط على الذاكرة ووحدة المعالجة المركزية. نأمل أن أجهزة الكمبيوتر المكتبية هي الدهون كافية للتعامل مع هذا. الهواتف المحمولة ليست قوية.


يتذكر AngularJS القيمة ويقارنها بقيمة سابقة. هذا هو فحص القذرة الأساسي. إذا كان هناك تغيير في القيمة ، فإنه يطلق حدث التغيير.

أسلوب $apply() ، وهو ما تقوم بالاتصال به عندما تقوم بالانتقال من عالم غير AngularJS إلى عالم AngularJS ، يقوم باستدعاء $digest() . إن الموجز هو مجرد فحص قديم قذر. يعمل على جميع المتصفحات ويمكن التنبؤ به تمامًا.

على النقيض من التدقيق القذرة (AngularJS) مقابل تغيير المستمعين ( KnockoutJS و Backbone.js ): بينما قد يبدو الفحص القذر بسيطًا ، وحتى غير كفء (سأعالج ذلك لاحقًا) ، يتبين أنه صحيح بشكل دلالي طوال الوقت ، في حين أن مستمعي التغيير لديهم الكثير من الحالات الزاوية الغريبة ويحتاجون إلى أشياء مثل تعقب التبعية لجعلها أكثر دلالة صحيحة. تتبع التبعية KnockoutJS هو ميزة ذكية لمشكلة لا تملك AngularJS.

مشكلات تغيير المستمعين:

  • البنية هي فظيعة ، لأن المتصفحات لا تدعمها أصلاً. نعم ، هناك وكلاء ، ولكنها ليست صحيحة دلاليًا في جميع الحالات ، وبالطبع لا يوجد بروكسيات على المتصفحات القديمة. خلاصة القول هي أن التدقيق القذر يسمح لك بالقيام بـ POJO ، في حين أن KnockoutJS و Backbone.js يجبرك على أن ترث من فصولهم ، والوصول إلى البيانات الخاصة بك من خلال accessors.
  • تغيير الاندماج. لنفترض أن لديك مجموعة من العناصر. لنفترض أنك تريد إضافة عناصر إلى مصفوفة ، كما تريد التكرار ، يمكنك في كل مرة تضيفك فيها إطلاق الأحداث على التغيير ، مما يؤدي إلى عرض واجهة المستخدم. هذا سيء للغاية للأداء. ما تريده هو تحديث واجهة المستخدم مرة واحدة فقط ، في النهاية. أحداث التغيير دقيقة للغاية.
  • تغيير المستمعين إطلاق النار على الفور على أداة تحديد ، وهي مشكلة ، حيث يمكن تغيير المستمع تغيير البيانات ، والذي يطلق المزيد من أحداث التغيير. هذا أمر سيئ لأنك قد تواجه أحداث تغيير عدة في وقت واحد. لنفترض أن لديك صفيفان يجب حفظهما متزامنين لأي سبب من الأسباب. يمكنك فقط إضافته إلى واحد أو آخر ، ولكن في كل مرة تضيفها ، يمكنك إطلاق حدث تغيير ، والذي أصبح الآن وجهة نظر غير متناسقة للعالم. هذه مشكلة مشابهة جدًا لتأمين الربط ، والذي يتجنبه جافا سكريبت لأن كل رد اتصال يُنفذ حصريًا وإتمامًا. تغيير الأحداث يكسر هذا لأن المستوطنين يمكن أن يكون لهم عواقب بعيدة المدى غير مقصودة وغير واضحة ، مما يخلق مشكلة الخيط مرة أخرى. وتبين أن ما تريد القيام به هو تأخير تنفيذ المستمع ، وضمان أن مستمعًا واحدًا يعمل في وقت واحد ، وبالتالي فإن أي كود مجاني لتغيير البيانات ، ويعلم أنه لا يوجد كود آخر يعمل أثناء قيامه بذلك. .

ماذا عن الأداء؟

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

البشر هم:

  • بطيء - أي شيء أسرع من 50 مللي ثانية غير محسوس على البشر ، وبالتالي يمكن اعتباره "فوري".

  • Limited - لا يمكنك عرض أكثر من 2000 قطعة من المعلومات لشخص في صفحة واحدة. أي شيء أكثر من ذلك هو واجهة المستخدم سيئة حقا ، والبشر لا يمكن معالجة هذا على أي حال.

لذا فإن السؤال الحقيقي هو: كم عدد المقارنات التي يمكنك القيام بها على متصفح في 50 مللي ثانية؟ هذا سؤال صعب للإجابة على العديد من العوامل ، ولكن هنا حالة اختبار: http://jsperf.com/angularjs-digest/6 الذي ينشئ 10000 مراقب. على متصفح حديث ، يستغرق هذا أقل من 6 مللي ثانية. في Internet Explorer 8 ، يستغرق حوالي 40 مللي ثانية. كما ترى ، هذه ليست مشكلة حتى على المتصفحات البطيئة هذه الأيام. هناك تحذير: يجب أن تكون المقارنات بسيطة لتتوافق مع الحد الزمني ... لسوء الحظ من السهل جدًا إضافة مقارنة بطيئة في AngularJS ، لذلك من السهل إنشاء تطبيقات بطيئة عندما لا تعرف ما تقوم به يفعلون. لكننا نأمل في الحصول على إجابة من خلال توفير وحدة الأجهزة ، والتي سوف تظهر لك ما هي المقارنات البطيئة.

وتبين أن ألعاب الفيديو ووحدات معالجة الرسومات تستخدم نهج التدقيق القذر ، وتحديدًا لأنها متناسقة. وطالما أنهم يحصلون على معدل تحديث الشاشة (عادة 50-60 هرتز ، أو كل 16.6-20 مللي ثانية) ، فإن أي أداء أكثر من ذلك يعتبر مضيعة ، لذا فأنت أفضل من رسم المزيد من الأشياء ، بدلاً من الحصول على FPS أعلى.


تساءلت هذا نفسي لفترة من الوقت. بدون حالات كيف يتغير AngularJS إلى كائن $scope ؟ هل يستطلعهم؟

ما يفعله في الواقع هو: أي مكان "طبيعي" قمت بتعديل النموذج كان يسمى بالفعل من أحشاء AngularJS ، لذلك يقوم تلقائيًا بالاتصال $apply لك بعد تشغيل التعليمات البرمجية. لنفترض أن جهاز التحكم لديك يحتوي على طريقة يتم ng-click على بعض العناصر. نظرًا لأن AngularJS تقوم بتوصيل استدعاء هذه الطريقة معًا ، فستتاح لك فرصة $apply في المكان المناسب. وبالمثل بالنسبة للتعبيرات التي تظهر مباشرة في وجهات النظر ، يتم تنفيذها بواسطة AngularJS بحيث يتم $apply .

عندما تتحدث الوثائق عن الاضطرار إلى الاتصال بـ $apply يدويًا للحصول على كود خارج AngularJS ، فإنه يتحدث عن الكود ، الذي لا ينبع ، عند تشغيله ، من AngularJS نفسه في مكدس الاستدعاءات.


قدمت Misko بالفعل وصفًا ممتازًا لكيفية عمل ارتباطات البيانات ، لكنني أود إضافة وجهة نظري حول مشكلة الأداء مع ربط البيانات.

كما ذكر Misko ، حوالي 2000 الارتباطات حيث تبدأ في رؤية المشاكل ، ولكن لا ينبغي أن يكون لديك أكثر من 2000 قطعة من المعلومات على صفحة على أي حال. قد يكون هذا صحيحًا ، لكن ليس كل ارتباط للبيانات مرئي للمستخدم. بمجرد البدء في إنشاء أي نوع من عناصر واجهة المستخدم أو شبكة البيانات مع التجليد ثنائي الاتجاه ، يمكنك بسهولة الوصول إلى 2000 رابط ، دون الحاجة إلى ux سيئة.

ضع في اعتبارك ، على سبيل المثال ، combobox حيث يمكنك كتابة نص لتصفية الخيارات المتوفرة. يمكن أن يكون هذا النوع من التحكم يحتوي على 150 عنصرًا وما زال صالحًا للاستخدام. إذا كان يحتوي على بعض الميزات الإضافية (على سبيل المثال فئة محددة على الخيار المحدد حاليًا) ، فستبدأ في الحصول على ارتباطات 3-5 لكل خيار. ضع ثلاثة من هذه الأدوات على الصفحة (على سبيل المثال ، اختر بلدًا ، والآخر لاختيار مدينة في البلد المذكور ، والثالث لتحديد فندق) وكنت في مكان ما بين 1000 و 2000 ارتباطات بالفعل.

أو النظر في شبكة البيانات في تطبيق ويب الشركات. 50 صف في كل صفحة ليس من غير المعقول ، كل منها يمكن أن يكون 10-20 عمود. إذا قمت ببناء هذا باستخدام ng-repeats ، و / أو لديك معلومات في بعض الخلايا التي تستخدم بعض الارتباطات ، قد تقترب من 2000 الارتباطات مع هذه الشبكة بمفردها.

أجد أن هذه مشكلة كبيرة عند العمل مع AngularJS ، والحل الوحيد الذي تمكنت من العثور عليه حتى الآن هو إنشاء عناصر واجهة مستخدم دون استخدام ربط ثنائي الاتجاه ، بدلاً من استخدام ngOnce ، أو إلغاء تسجيل المراقبين والحيل المماثلة ، أو بناء التوجيهات مما ينشئ DOM مع معالجة jQuery و DOM. أشعر أن هذا يهزم الهدف من استخدام Angular في المقام الأول.

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

TL، DR
يمكن أن يتسبب ربط البيانات في حدوث مشكلات في الأداء على الصفحات المعقدة.


كان صديق يواجه مشاكل في Internet Explorer 8 ، وأظهر لي ما فعله. قلت له أنه كان خطأ ، وقال لي أنه حصل على الجواب هنا. لن تعمل الإجابة الأعلى الحالية في جميع المتصفحات (Internet Explorer 8 على سبيل المثال) ، وستقوم فقط بإزالة التواجد الأول للعنصر.

قم بإزالة كافة المثيلات من صفيف

function remove(arr, item) {
    for (var i = arr.length; i--;) {
        if (arr[i] === item) {
            arr.splice(i, 1);
        }
    }
}

يتدفق عبر الصفيف للخلف (بما أن الفهارس والطول سيتغيران عند إزالة العناصر) ويزيل العنصر إذا تم العثور عليه. يعمل في جميع المتصفحات.





javascript angularjs data-binding