মার্কফোরচেক () এবং ডিটেক্টচেনজেস () এর মধ্যে পার্থক্য কী


174

মধ্যে পার্থক্য কি ChangeDetectorRef.markForCheck()এবং ChangeDetectorRef.detectChanges()?

আমি কেবলমাত্র এসও সম্পর্কিত তথ্য পেয়েছি পার্থক্য হিসাবে NgZone.run(), তবে এই দুটি ফাংশনের মধ্যে নয়।

কেবলমাত্র ডকটির একটি রেফারেন্স সহ উত্তরের জন্য, দয়া করে একটির অন্যটির থেকে বেছে নিতে কিছু ব্যবহারিক পরিস্থিতি বর্ণনা করুন।



@ মিলাদ আপনি কীভাবে জানেন যে তিনি এটি হ্রাস করেছেন? এই সাইটটি অনুধাবন করার মতো অনেক লোক রয়েছে।
বিদায় স্ট্যাক এক্সচেঞ্জ 15

2
@ ফ্র্যাঙ্কজার আমার মনে".
মিলাদ

3
ডাউনওয়েটটি মূল উত্তরটি সম্পূর্ণ করতে আপনাকে উত্সাহিত করেছিল যা আমি ইতিমধ্যে দেখেছি এমন ডক্স থেকে অনুলিপি করে আটকানো হয়েছিল। এবং এটা কাজ করে! এখন উত্তরটির অনেক স্পষ্টতা রয়েছে এবং এটি গ্রহণযোগ্য উত্তর, ধন্যবাদ:)
সংসদ

3
@ পার্লামেন্টে কী কুরুচিপূর্ণ পরিকল্পনা!
হ্যাঙ্ককা 26'17

উত্তর:


234

ডক্স থেকে:

সনাক্তকরণ (): শূন্য

পরিবর্তন ডিটেক্টর এবং তার শিশুদের পরীক্ষা করে।

এর অর্থ হ'ল যদি এমন কোনও ঘটনা ঘটে থাকে যেখানে আপনার মডেলের অভ্যন্তরের কোনও কিছু (আপনার শ্রেণি) পরিবর্তিত হয়েছে তবে এটি দৃষ্টিভঙ্গিকে প্রতিফলিত করে না, আপনাকে সেই পরিবর্তনগুলি সনাক্ত করতে (স্থানীয় পরিবর্তনগুলি সনাক্ত করতে) এবং ভিউটি আপডেট করার জন্য অ্যাংুলারকে অবহিত করতে হবে।

সম্ভাব্য পরিস্থিতিগুলি হ'ল:

1- পরিবর্তন ডিটেক্টরটি ভিউ থেকে আলাদা করা হয় ( বিচ্ছিন্ন দেখুন )

2- একটি আপডেট হয়েছে তবে এটি কৌণিক অঞ্চলের মধ্যে ছিল না, সুতরাং কৌণিক এটি সম্পর্কে জানে না।

কোনও তৃতীয় পক্ষের ক্রিয়াকলাপ যখন আপনার মডেলটিকে আপডেট করেছে এবং আপনি তার পরে ভিউটি আপডেট করতে চান Like

 someFunctionThatIsRunByAThirdPartyCode(){
     yourModel.text = "new text";
 }

এই কোডটি কৌণিক অঞ্চলের বাইরে সম্ভবত (সম্ভবত), আপনাকে সম্ভবত পরিবর্তনগুলি সনাক্ত করতে এবং ভিউটি আপডেট করার বিষয়টি নিশ্চিত করতে হবে, সুতরাং:

 myFunction(){
   someFunctionThatIsRunByAThirdPartyCode();

   // Let's detect the changes that above function made to the model which Angular is not aware of.
    this.cd.detectChanges();
 }

দ্রষ্টব্য :

উপরের কাজ করার অন্যান্য উপায় রয়েছে, অন্য কথায়, কৌনিক পরিবর্তন চক্রের ভিতরে পরিবর্তন আনার অন্যান্য উপায়ও রয়েছে।

** আপনি এই অঞ্চলে তৃতীয় পক্ষের কার্যটি গুটিয়ে রাখতে পারেন could রুন:

 myFunction(){
   this.zone.run(this.someFunctionThatIsRunByAThirdPartyCode);
 }

** আপনি একটি সেটটাইমআউট ভিতরে ফাংশন মোড়ানো করতে পারে:

myFunction(){
   setTimeout(this.someFunctionThatIsRunByAThirdPartyCode,0);
 }

3- এমন কিছু ঘটনাও রয়েছে যেখানে আপনি মডেলটি আপডেট করার পরে আপডেট করেন change detection cycle, যেখানে এই ক্ষেত্রে আপনি এই ভয়ঙ্কর ত্রুটি পান:

"এটি যাচাই করার পরে অভিব্যক্তি পরিবর্তন হয়েছে";

এর সাধারণত অর্থ হয় (কৌণিক ভাষা থেকে):

আমি আপনার মডেলটিতে এমন একটি পরিবর্তন দেখেছি যা আমার গ্রহণযোগ্য উপায়ে (ইভেন্টস, এক্সএইচআর অনুরোধগুলি, সেটটাইমআউট এবং ...) এর ফলে ঘটেছিল এবং তারপরে আমি আপনার দৃষ্টিভঙ্গিটি আপডেট করতে আমার পরিবর্তন সনাক্তকরণ চালিয়েছি এবং এটি শেষ করেছি, তবে তার পরে অন্যটি ছিল আপনার কোডে ফাংশন যা মডেলটি আবার আপডেট করেছে এবং আমি আবার আমার পরিবর্তন সনাক্তকরণ চালাতে চাই না কারণ AngularJS এর ​​মতো আর কোনও নোংরা চেকিং নেই: ডি এবং আমাদের একতরফা ডেটা প্রবাহ ব্যবহার করা উচিত!

আপনি অবশ্যই এই ত্রুটিটি দেখতে পাবেন: পি।

এটি ঠিক করার কয়েকটি উপায়:

1- যথাযথ উপায় : নিশ্চিত করুন যে আপডেটটি পরিবর্তন সনাক্তকরণ চক্রের অভ্যন্তরে রয়েছে (অ্যাঙ্গুলার 2 আপডেটগুলি একবারে প্রবাহিত হয় যা একবার হয়, তার পরে মডেলটি আপডেট করবেন না এবং আপনার কোডটিকে আরও ভাল জায়গায় / সময় নিয়ে যান)।

2- অলস উপায় : কৌনিক 2 কে খুশি করার জন্য আপডেটের পরে সনাক্ত করুন চেঞ্জস () চালান, এটি অবশ্যই সেরা উপায় নয়, তবে আপনি যেমনটি জিজ্ঞাসা করেছিলেন যে সম্ভাব্য পরিস্থিতিগুলি কী, এটি তাদের মধ্যে একটি।

এইভাবে আপনি বলছেন: আমি সত্যই জানি যে আপনি পরিবর্তনটি সনাক্ত করতে পেরেছিলেন তবে আমি আপনাকে আবার এটি করতে চাই কারণ আপনি চেকিং শেষ করার পরে আমাকে ফ্লাইতে কিছু আপডেট করতে হয়েছিল।

3- কোডটি একটি এর ভিতরে রাখুন setTimeout, কারণ setTimeoutজোনের দ্বারা প্যাচ করা হয় এবং detectChangesএটি শেষ হয়ে গেলে চলবে ।


ডক্স থেকে

markForCheck() : void

যাচাই করা হয়েছে এমন সমস্ত চেঞ্জডেস্টেকশনস্ট্রেজি পূর্বপুরুষকে চিহ্নিত করে।

অধিকাংশ ক্ষেত্রে এই প্রয়োজন যখন হয় ChangeDetectionStrategy আপনার উপাদানের হয় OnPush

অনপশ নিজেই এর অর্থ হ'ল, এর মধ্যে যদি কিছু ঘটে থাকে তবে কেবল পরিবর্তন সনাক্ত করুন:

1- উপাদানগুলির @ ইনপুটগুলির মধ্যে একটি সম্পূর্ণরূপে একটি নতুন মান দিয়ে প্রতিস্থাপিত হয়েছে, বা যদি সহজভাবে বলা যায়, যদি @ ইনপুট সম্পত্তির রেফারেন্স পুরোপুরি পরিবর্তিত হয়।

তাই আপনি যদি ChangeDetectionStrategy আপনার উপাদানের হয় OnPush এবং তারপর আপনি আছে:

   var obj = {
     name:'Milad'
   };

এবং তারপরে আপনি এটিকে আপডেট / পরিবর্তন করুন:

  obj.name = "a new name";

এটি আপত্তি রেফারেন্স আপডেট করবে না , অতএব পরিবর্তন সনাক্তকরণ চলে না, সুতরাং ভিউ আপডেট / মিউটেশনকে প্রতিফলিত করে না।

এই ক্ষেত্রে আপনাকে অ্যাঙ্গুলারটি ম্যানুয়ালি বলতে হবে ভিউটি পরীক্ষা করতে এবং আপডেট করতে (মার্কফোর্ড);

সুতরাং আপনি যদি এটি করেন:

  obj.name = "a new name";

আপনার এটি করা দরকার:

  this.cd.markForCheck();

বরং নীচে পরিবর্তনের ফলে সনাক্তকরণ চালানো হবে:

    obj = {
      name:"a new name"
    };

যা সম্পূর্ণ পূর্ববর্তী আপত্তিটিকে নতুন করে প্রতিস্থাপন করেছে {};

2- একটি ইভেন্ট বা ক্লিকের মতো কিছু বা তার মতো বা শিশু উপাদানগুলির মতো কোনও ইভেন্ট ছুড়েছে event

ইভেন্টগুলি:

  • ক্লিক
  • keyup
  • সাবস্ক্রিপশন ইভেন্ট
  • প্রভৃতি

সংক্ষেপে:

  • detectChanges()কৌণিক চলার পরে যখন আপনি মডেলটি আপডেট করেছেন তখন এটির পরিবর্তন সনাক্তকরণ ব্যবহার করুন, বা আপডেটটি কৌণিক বিশ্বে মোটেও হয়নি Use

  • ব্যবহারের markForCheck()আপনি OnPush ব্যবহার করা হয় তবে করছি এবং আপনি বাইপাস করছি ChangeDetectionStrategyকিছু ডেটা mutating দ্বারা অথবা আপনি একটি ভিতরে মডেল আপডেট করেছি setTimeout ;


6
সুতরাং যদি আপনি এই আপত্তিটি পরিবর্তন করেন তবে দৃশ্যটি আপডেট হবে না এবং আপনি সনাক্তকরণ পরিবর্তন চালিয়ে গেলেও কোনও কাজ হবে না কারণ কোনও পরিবর্তন হয়নি because হয়নি this এটি সত্য নয়। detectChangesআপডেট ভিউ। দেখুন এই গভীর ব্যাখ্যা
ম্যাক্স কোরেটস্কি

উপসংহারে চিহ্নফোরচেক সম্পর্কে, এটিও সঠিক নয়। এই প্রশ্ন থেকে পরিবর্তিত উদাহরণ এখানে's , এটি অনপশ এবং মার্কফোরচেকের সাহায্যে অবজেক্টের পরিবর্তনগুলি সনাক্ত করতে পারে না। তবে অনপশ কৌশল না থাকলে একই উদাহরণ কাজ করবে
এস্তাস ফ্লাস্ক

@ ম্যাক্সিমাস, আপনার প্রথম মন্তব্য সম্পর্কে, আমি আপনার পোস্টটি পড়েছি, ধন্যবাদ যে এটি ভাল ছিল। তবে আপনার ব্যাখ্যায় আপনি বলছেন যে কৌশলটি অনপশ, যদি এর অর্থ this.cdMode === ChangeDetectorStatus.Checkedভিউ আপডেট না করে তবে আপনি মার্কফোরচেক ব্যবহার করবেন।
মিলাদ

এবং প্লাঙ্কারের সাথে আপনার লিঙ্কগুলি সম্পর্কে, উভয় উদাহরণই আমার পক্ষে ভাল কাজ করছে, আপনার অর্থ কী তা আমি জানি না
মিলাদ

@ মিলাদ, এই মন্তব্যগুলি @estus :) থেকে এসেছে। আমার সম্পর্কে ছিল detectChanges। এবং cdModeকৌণিক কোন নেই 4.x.x। আমি আমার নিবন্ধে যে সম্পর্কে লিখুন। আনন্দিত আপনি এটা পছন্দ করেছেন. ভুলে যাবেন না আপনি এটি মিডিয়ামে সুপারিশ করতে পারেন বা আমাকে অনুসরণ করতে পারেন :)
ম্যাক্স কোরটস্কি

99

দুজনের মধ্যে সবচেয়ে বড় পার্থক্য হ'ল detectChanges()আসলে পরিবর্তন সনাক্তকরণকে markForCheck()ট্রিগার করে , যখন পরিবর্তন সনাক্তকরণকে ট্রিগার করে না।

detectChanges

আপনি যে ট্রিগারটি চালু করছেন সেই উপাদান দিয়ে গাছের গাছের পরিবর্তন সনাক্তকরণের জন্য এটি ব্যবহার করা detectChanges()হয়। সুতরাং পরিবর্তন সনাক্তকরণ বর্তমান উপাদান এবং এর সমস্ত শিশুদের জন্য চলবে। কৌণিকটি মূল উপাদান গাছের সাথে রেফারেন্স ধারণ করে ApplicationRefএবং যখন কোনও অ্যাসিঙ্ক অপারেশন ঘটে তখন এটি একটি মোড়ক পদ্ধতির মাধ্যমে এই মূল উপাদানটিতে সনাক্তকরণ পরিবর্তন করে tick():

@Injectable()
export class ApplicationRef_ extends ApplicationRef {
  ...
  tick(): void {
    if (this._runningTick) {
      throw new Error('ApplicationRef.tick is called recursively');
    }

    const scope = ApplicationRef_._tickScope();
    try {
      this._runningTick = true;
      this._views.forEach((view) => view.detectChanges()); <------------------

viewএখানে মূল উপাদান দেখুন। অনেকগুলি মূল উপাদান থাকতে পারে যেমন আমি বর্ণনা করেছি যে একাধিক উপাদান বুটস্ট্র্যাপিংয়ের কী কী প্রভাব রয়েছে

@ মিলাদ আপনার নিজেরাই কীভাবে পরিবর্তন শনাক্তকরণের প্রয়োজন হতে পারে তার কারণ বর্ণনা করেছেন।

markForCheck

যেমনটি আমি বলেছিলাম, এই লোকটি পরিবর্তন সনাক্তকরণ মোটেও ট্রিগার করে না। এটি কেবলমাত্র সরল উপাদান থেকে মূল অংশে উপরের দিকে যায় এবং তাদের দৃশ্যের স্থিতিতে আপডেট করে ChecksEnabled। উত্স কোডটি এখানে:

export function markParentViewsForCheck(view: ViewData) {
  let currView: ViewData|null = view;
  while (currView) {
    if (currView.def.flags & ViewFlags.OnPush) {
      currView.state |= ViewState.ChecksEnabled;  <-----------------
    }
    currView = currView.viewContainerParent || currView.parent;
  }
}

উপাদানটির প্রকৃত পরিবর্তন সনাক্তকরণ নির্ধারিত নয় তবে ভবিষ্যতে কখন তা ঘটবে (বর্তমান বা পরবর্তী সিডি চক্রের অংশ হিসাবে) প্যারেন্ট উপাদানগুলির দর্শনগুলি যদি তাদের সনাক্তকারী সনাক্তকরণ বিচ্ছিন্ন করে রেখেছিল তাও পরীক্ষা করা হবে। পরিবর্তন সনাক্তকারী কৌশলটি ব্যবহার করে cd.detach()বা OnPushপরিবর্তন সনাক্তকরণ কৌশল নির্দিষ্ট করে আলাদা করা যেতে পারে । সমস্ত নেটিভ ইভেন্ট হ্যান্ডলারগুলি চেকের জন্য সমস্ত অভিভাবক উপাদান দর্শন চিহ্নিত করে।

এই পদ্ধতির প্রায়শই ব্যবহৃত হয় ngDoCheck লাইফসাইক্ল হুক । আপনি যদি আরও মনে করেন ngDoCheckযে আপনার উপাদানটি চেক করা হচ্ছে তার মানে আপনি আরও পড়তে পারেন - এই নিবন্ধটি পড়ুন

আরও তথ্যের জন্য কৌণিক পরিবর্তন সনাক্তকরণ সম্পর্কে আপনার যা যা জানা দরকার সেগুলিও দেখুন ।


1
কেন আবিষ্কারকারীগুলি উপাদান এবং পূর্বপুরুষদের চিহ্নিত করে ফোরফোর চেক করার সময় উপাদান এবং তার শিশুদের উপর কাজ করে?
পাবলো

@ পাবলো, এটি ডিজাইনের মাধ্যমে। আমি যুক্তির সাথে সত্যই পরিচিত নই
ম্যাক্স কোরেস্তস্কি

@ AngularInDepth.com যদি খুব নিবিড় প্রক্রিয়াজাতকরণ হয় তবে চেঞ্জডিটেকশনটি ইউআইকে ব্লক করে?
alt255

1
@ জেরি, প্রস্তাবিত পন্থা হ'ল অ্যাসিঙ্ক পাইপ ব্যবহার করা, যা অভ্যন্তরীণভাবে সাবস্ক্রিপশন এবং প্রতিটি নতুন মান ট্রিগারগুলিতে ট্র্যাক করে markForCheck। সুতরাং আপনি যদি অ্যাসিঙ্ক পাইপ ব্যবহার না করেন তবে সম্ভবত এটিই আপনার ব্যবহার করা উচিত। তবে, মনে রাখবেন যে স্টোর আপডেটটি পরিবর্তন শনাক্তকরণ শুরুর জন্য কিছু অ্যাসিঙ্ক ইভেন্টের ফলাফল হিসাবে হওয়া উচিত। সর্বাধিক ক্ষেত্রে এটি হয়। তবে ব্যতিক্রমগুলি রয়েছে blog.angularindepth.com/…
ম্যাক্স কোরেটস্কিই

1
উত্তর: ম্যাক্সকরেটস্কিইকা উইজার্ড ধন্যবাদ হ্যাঁ স্টোর আপডেটটি বেশিরভাগই ফিচার আনার বা সেটিংসের ফলাফল et এবং আনার পরে .. তবে async pipeসাবস্ক্রাইবটির অভ্যন্তরে আমরা সবসময় ব্যবহার করতে পারি না কারণ আমাদের সাধারণত কিছু জিনিস পছন্দ করতে হয় call setFromValues do some comparison.. এবং যদি আমরা asyncনিজেই ফোন করি markForCheckতবে সমস্যাটি কী বলে? তবে আবার আমাদের সাধারণত ngOnInitবিভিন্ন ডেটা পাওয়ার ক্ষেত্রে 2-3 বা কখনও কখনও আরও বেশি নির্বাচক থাকে ... এবং আমরা তাদের markForCheckসকলকে কল করি .. এটি কি ঠিক আছে?
জেরি

0

cd.detectChanges() বর্তমান উপাদান থেকে অবিলম্বে এর বংশধরদের মাধ্যমে পরিবর্তন সনাক্তকরণ চালাবে।

cd.markForCheck()পরিবর্তন সনাক্তকরণ চালাবে না, তবে পরিবর্তন সনাক্তকরণ চালানোর জন্য এটি পূর্বপুরুষদের চিহ্নিত করুন। পরবর্তী সময় পরিবর্তন সনাক্তকরণ যে কোনও জায়গায় চলবে, এটি চিহ্নিত করা হয়েছে এমন উপাদানগুলির জন্যও এটি চলবে।

  • আপনি সময়ের সংখ্যা হ্রাস করতে চাইলে সনাক্তকরণকে ব্যবহার বলা হয় cd.markForCheck()। প্রায়শই পরিবর্তনগুলি একাধিক উপাদানকে প্রভাবিত করে এবং কোথাও পরিবর্তন সনাক্তকরণ ডাকা হবে। আপনি মূলত বলছে: আসুন ঠিক নিশ্চিত এই উপাদানটি কি না নিশ্চিত করুন এছাড়াও আপডেট যখন যে ঘটবে। (আমি লিখেছি প্রতিটি প্রকল্পে দৃশ্য অবিলম্বে আপডেট করা হয় তবে প্রতিটি ইউনিট পরীক্ষায় নয়)।
  • আপনি যদি নিশ্চিত হতে না পারেন যে বর্তমানে পরিবর্তনটি সনাক্তকরণ চলছেcd.detectChanges() না , তবে ব্যবহার করুন । এই ক্ষেত্রে ত্রুটি হবে। এর অর্থ সম্ভবত আপনি পূর্বসূরি উপাদানটির অবস্থা সম্পাদনা করার চেষ্টা করছেন যা অ্যাঙ্গুলারের পরিবর্তন সনাক্তকরণ চারপাশে নকশা করা হয়েছে এমন অনুমানের বিরুদ্ধে কাজ করছে। cd.markForCheck()detectChanges()
  • যদি এটি গুরুত্বপূর্ণ হয় যে ভিউ আপডেটটি কিছু অন্যান্য ক্রিয়াকলাপের আগে সিঙ্ক্রোনসিভ করে, ব্যবহার করুন detectChanges()markForCheck()সময় মত আপনার ভিউ আসলে আপডেট নাও করতে পারে। fixture.detectChanges()কোনও কিছুর ইউনিট পরীক্ষা করা আপনার দৃষ্টিভঙ্গিকে প্রভাবিত করে, উদাহরণস্বরূপ, অ্যাপ্লিকেশনটিতে যখন এটি প্রয়োজনীয় ছিল না তখন আপনাকে ম্যানুয়ালি কল করতে হতে পারে।
  • যদি আপনি বংশধরদের চেয়ে আরও পূর্বপুরুষের সাথে একটি উপাদানে রাষ্ট্র পরিবর্তন করে থাকেন তবে আপনি ব্যবহারের মাধ্যমে পারফরম্যান্স বৃদ্ধি পেতে পারেন detectChanges()যেহেতু আপনি উপাদানটির পূর্বপুরুষদের অকারণে পরিবর্তন সনাক্তকরণ চালাচ্ছেন না।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.