সমস্যা এবং সম্ভাব্য সমাধানগুলি পুরোপুরি বুঝতে, পাইপ এবং উপাদানগুলির জন্য - আমাদের কৌনিক পরিবর্তন সনাক্তকরণ নিয়ে আলোচনা করা উচিত।
পাইপ পরিবর্তন সনাক্তকরণ
রাষ্ট্রহীন / খাঁটি পাইপ
ডিফল্টরূপে, পাইপগুলি রাষ্ট্রবিহীন / খাঁটি। স্টেটলেস / খাঁটি পাইপগুলি কেবল ইনপুট ডেটাগুলিকে আউটপুট ডেটাতে রূপান্তর করে। তারা কিছুই মনে রাখে না, তাই তাদের কোনও সম্পত্তি নেই - কেবল একটি transform()পদ্ধতি। কৌণিক স্ট্যাটাসহীন / খাঁটি পাইপের চিকিত্সা অনুকূল করতে পারে: যদি তাদের ইনপুটগুলি পরিবর্তন না হয় তবে পরিবর্তনগুলি সনাক্তকরণ চক্রের সময় পাইপগুলি কার্যকর করার প্রয়োজন হয় না। একটি নল জন্য যেমন {{power | exponentialStrength: factor}}, powerএবং factorইনপুট আছে।
এই প্রশ্নের জন্য "#student of students | sortByName:queryElem.value", studentsএবং queryElem.valueইনপুট হয় এবং পাইপ sortByNameরাষ্ট্রবিহীন / খাঁটি। studentsএকটি অ্যারে (রেফারেন্স)।
- যখন কোনও ছাত্র যুক্ত করা হয় তখন অ্যারের উল্লেখটি পরিবর্তিত
studentsহয় না - পরিবর্তিত হয় না - সুতরাং রাষ্ট্রবিহীন / খাঁটি পাইপ কার্যকর হয় না।
- যখন ফিল্টার ইনপুটটিতে কিছু টাইপ করা হয় তখন
queryElem.valueতা পরিবর্তিত হয়, সুতরাং স্টেটলেস / খাঁটি পাইপ কার্যকর করা হয়।
অ্যারে ইস্যুটি সংশোধন করার একটি উপায় হ'ল প্রতিটি শিক্ষার্থী যুক্ত হওয়ার সাথে সাথে অ্যারে রেফারেন্সটি পরিবর্তন করা - অর্থাত্ প্রতিটি সময় শিক্ষার্থী যুক্ত হওয়ার পরে একটি নতুন অ্যারে তৈরি করা। আমরা এটি দিয়ে এটি করতে পারি concat():
this.students = this.students.concat([{name: studentName}]);
যদিও এটি কাজ করে, addNewStudent()কেবলমাত্র আমরা পাইপ ব্যবহার করার কারণে আমাদের পদ্ধতিটি একটি নির্দিষ্ট উপায়ে কার্যকর করা উচিত নয়। আমরা push()আমাদের অ্যারেতে যুক্ত করতে ব্যবহার করতে চাই ।
রাষ্ট্রীয় পাইপ
রাষ্ট্রীয় পাইপগুলির স্টেট থাকে - তাদের সাধারণত বৈশিষ্ট্য থাকে, কেবল কোনও transform()পদ্ধতি নয়। তাদের ইনপুটগুলি পরিবর্তন না হলেও এমনকি তাদের মূল্যায়ন করা প্রয়োজন। যখন আমরা উল্লেখ করি যে একটি পাইপ স্থিতিশীল / অ-খাঁটি - pure: false- তবে যখনই অ্যাংুলারের পরিবর্তন সনাক্তকরণ সিস্টেম পরিবর্তনগুলির জন্য কোনও উপাদান পরীক্ষা করে এবং সেই উপাদানটি স্টেটফুল পাইপ ব্যবহার করে, তখন পাইপটির আউটপুট পরীক্ষা করা হবে কিনা, তার ইনপুট পরিবর্তন হয়েছে কি না।
এটি কম দক্ষ হলেও আমরা যা চাই তা মনে হচ্ছে, যেহেতু আমরা চাইছি studentsরেফারেন্স পরিবর্তিত না হয়েও পাইপটি কার্যকর করা হোক। যদি আমরা কেবল পাইপটিকে রাষ্ট্রীয় করে তুলি তবে আমরা একটি ত্রুটি পেয়েছি:
EXCEPTION: Expression 'students | sortByName:queryElem.value in HelloWorld@7:6'
has changed after it was checked. Previous value: '[object Object],[object Object]'.
Current value: '[object Object],[object Object]' in [students | sortByName:queryElem.value
@ ড্র্রুমুরের জবাব অনুসারে , "এই ত্রুটিটি কেবলমাত্র ডেভ মোডে ঘটে (যা বিটা -0 হিসাবে ডিফল্টরূপে সক্ষম হয়) enableProdMode()app অ্যাপটি বুটস্ট্র্যাপ করার সময় আপনি যদি কল করেন, ত্রুটিটি নিক্ষেপ করা হবে না।" এর জন্য দস্তাবেজApplicationRef.tick() রাজ্য:
বিকাশ মোডে, আরও কোনও পরিবর্তন সনাক্ত না হয় তা নিশ্চিত করতে টিক () এছাড়াও দ্বিতীয় পরিবর্তন সনাক্তকরণ চক্র সম্পাদন করে। যদি এই দ্বিতীয় চক্রের সময় অতিরিক্ত পরিবর্তনগুলি গ্রহণ করা হয় তবে অ্যাপ্লিকেশনটিতে বাইন্ডিংগুলির পার্শ্ব-প্রতিক্রিয়া রয়েছে যা একক পরিবর্তন সনাক্তকরণের পাসে সমাধান করা যায় না। এই ক্ষেত্রে, কৌণিক একটি ত্রুটি নিক্ষেপ করে, যেহেতু একটি কৌণিক অ্যাপ্লিকেশনটিতে কেবল একটি পরিবর্তন সনাক্তকরণ পাস থাকতে পারে যার সময় সমস্ত পরিবর্তন সনাক্তকরণ সম্পূর্ণ করতে হবে।
আমাদের দৃশ্যে আমি বিশ্বাস করি ত্রুটিটি বোগাস / বিভ্রান্তিকর। আমাদের একটি রাষ্ট্রীয় পাইপ রয়েছে এবং প্রতিবার এটি আউটপুট পরিবর্তিত হতে পারে - এর পার্শ্ব প্রতিক্রিয়া থাকতে পারে এবং এটি ঠিক আছে। এনজিফোর্ড পাইপের পরে মূল্যায়ন করা হয়, সুতরাং এটি ঠিকঠাক কাজ করা উচিত।
তবে, এই ত্রুটিটি নিক্ষেপ করার সাথে আমরা সত্যিকার অর্থে বিকাশ করতে পারি না, সুতরাং পাইপ প্রয়োগের ক্ষেত্রে একটি অ্যারে সম্পত্তি (অর্থাত্ রাষ্ট্র) যুক্ত করা এবং সর্বদা সেই অ্যারেটি ফিরিয়ে ফেলা উচিত work এই সমাধানের জন্য @ পিক্সেলবিতের উত্তর দেখুন।
তবে, আমরা আরও দক্ষ হতে পারি এবং যেমনটি আমরা দেখতে পাব পাইপ প্রয়োগের জন্য আমাদের অ্যারে সম্পত্তি প্রয়োজন হবে না এবং দ্বিগুণ পরিবর্তন সনাক্তকরণের জন্য আমাদের কোনও কাজের প্রয়োজন হবে না।
উপাদান পরিবর্তন সনাক্তকরণ
ডিফল্টরূপে, প্রতিটি ব্রাউজার ইভেন্টে, কৌনিক পরিবর্তন সনাক্তকরণ প্রতিটি উপাদানকে এটি পরিবর্তন হয়েছে কিনা তা দেখার জন্য যায় - ইনপুট এবং টেম্পলেট (এবং সম্ভবত অন্যান্য জিনিস?) চেক করা হয়েছে।
যদি আমরা জানি যে কোনও উপাদান কেবল তার ইনপুট বৈশিষ্ট্যগুলি (এবং টেম্পলেট ইভেন্টগুলি) এবং ইনপুট বৈশিষ্ট্যগুলি অপরিবর্তনীয় উপর নির্ভর করে তবে আমরা আরও কার্যকর দক্ষ onPushপরিবর্তন সনাক্তকরণ কৌশলটি ব্যবহার করতে পারি । এই কৌশলটি সহ, প্রতিটি ব্রাউজার ইভেন্ট পরীক্ষা করার পরিবর্তে ইনপুটগুলি পরিবর্তন করা হয় এবং টেমপ্লেট ইভেন্টগুলি ট্রিগার করা হয় কেবল তখনই একটি উপাদান চেক করা হয়। এবং, স্পষ্টতই, আমরা Expression ... has changed after it was checkedএই সেটিংটি দিয়ে ত্রুটিটি পাই না । এটি কারণ যে কোনও onPushউপাদান আবার "চিহ্নিত" ( ChangeDetectorRef.markForCheck()) না হওয়া অবধি পুনরায় পরীক্ষা করা হয় না । সুতরাং টেম্পলেট বাইন্ডিংগুলি এবং রাষ্ট্রীয় পাইপ আউটপুটগুলি একবার কার্যকর করা / মূল্যায়ন করা হয়। স্টেটলেস / খাঁটি পাইপগুলির ইনপুটগুলি পরিবর্তন না করা হলে এখনও কার্যকর করা হয় না। সুতরাং আমাদের এখনও একটি রাষ্ট্রীয় পাইপ প্রয়োজন।
@ এরিকমার্টিনিজ প্রস্তাবিত সমাধানটি হ'ল: onPushপরিবর্তন সনাক্তকরণ সহ রাষ্ট্রীয় পাইপ । এই সমাধানের জন্য @ ক্যাফিনেটমোনকি'র উত্তর দেখুন।
নোট করুন যে এই সমাধানের সাথে transform()পদ্ধতিটিতে প্রতিবার একই অ্যারে ফেরত দেওয়ার দরকার হয় না। আমি দেখতে পাই যে কিছুটা অদ্ভুত: একটি রাজ্যহীন পাইপ state এটি সম্পর্কে আরও কিছু ভেবে ... রাষ্ট্রীয় পাইপ সম্ভবত সর্বদা একই অ্যারে ফিরে আসবে। অন্যথায় এটি onPushডেভ মোডের উপাদানগুলির সাথেই ব্যবহার করা যেতে পারে ।
সুতরাং এতকিছুর পরেও, আমি মনে করি আমি @ এরিক এবং @ পিক্সেলবিটের উত্তরগুলির সংমিশ্রণটি পছন্দ করি: স্টেটফুল পাইপ যা onPushউপাদানটি অনুমতি দেয় তবে পরিবর্তন সনাক্তকরণ সহ একই অ্যারে রেফারেন্সটি ফিরিয়ে দেয়। যেহেতু রাষ্ট্রীয় পাইপ একই অ্যারে রেফারেন্স দেয়, পাইপটি এখনও সেই উপাদানগুলির সাথে ব্যবহার করা যেতে পারে যা কনফিগার করা হয়নি onPush।
Plunker
এটি সম্ভবত একটি কৌনিক 2 আইডিয়াম হয়ে উঠবে: যদি কোনও অ্যারে কোনও পাইপ খাওয়াত, এবং অ্যারে পরিবর্তন হতে পারে (অ্যারেতে থাকা আইটেমগুলি, অ্যারের উল্লেখ নয়), আমাদের স্টেটফুল পাইপ ব্যবহার করা দরকার।
pure:falseআপনার পাইপ, এবংchangeDetection: ChangeDetectionStrategy.OnPushআপনার কম্পোনেন্ট হবে।