جاوااسکریپت - چگونه تشخیص تغییر را مدیریت کنم وقتی از runOutsideAngular fromEvent استفاده میکنم؟
در برنامه انگولار خود به رویداد resize گوش میکنم و نام نقطه شکست را در موضوع breakpointChanged بهروزرسانی میکنم:
breakpointChanged = new Subject();
resize$ = fromEvent(window, "resize").pipe(
startWith(() => []),
map(() => [window.innerHeight, window.innerWidth]),
tap(([height, width]) => {
const name = this.breakpoint(width);
this.breakpointChanged.next(name);
})
);
بر اساس نام نقطه شکست تصمیم گرفتم که کشو باز باشد یا نه:
drawerOpened$ = this.breakpointChanged.pipe(
distinctUntilChanged(),
map((breakpointName) => {
return breakpointName !== "xs"; // if it's not xs breakpoint then it's true mean it's open.
})
);
من همچنین میخواهم از distinctUntilChanged استفاده کنم زیرا اگر نقطه شکست تغییر نکرده باشد، نمیخواهم جریان فعال شود.
و در ngOnInit من به جریان resize مشترک میشوم. و این کار را در runOutsideAngular انجام میدهم، بنابراین هر بار که تغییر اندازه رخ میدهد، تشخیص تغییر را فعال نمیکنم.
this.zone.runOutsideAngular(() => {
this.resize$.subscribe();
});
مشکل این است که نما بهروزرسانی نمیشود.
فقط وقتی که من this.breakpointChanged.next(name); را با this.zone.run(() => {}) میبندم، کار میکند، اما اگر این کار را انجام دهم، تشخیص تغییر فعال میشود - همیشه وقتی تغییر اندازه اتفاق میافتد. که این موضوع بد است.
ایدهای داری که چطور این مشکل را حل کنیم و آن را مرتب و تمیز کنیم؟
در همان زمینه، چگونه لوله async تشخیص تغییر انجام نمیدهد؟ مقدار در حال تغییر است و async باید مشترک شود و زمانی که مقدار تغییر میکند، فعال شود.
codesandbox.io
پاسخ شماره ۱
این سوال خوبی است. ممکن است بتوانیم پیچیدگی را با استفاده از debounceTime() به صورت زیر کاهش دهیم:
resize$ = fromEvent(window, "resize").pipe(
startWith(() => []),
debounceTime(1000),
map(() => [window.innerHeight, window.innerWidth]),
tap(([height, width]) => {
console.log(height);
const name = this.breakpoint(width);
this.breakpointChanged.next(name);
})
);
و حذف this.zone.runOutsideAngular
ngOnInit() {
this.resize$.subscribe();
}
مهم نیست چند بار تغییر اندازه داده شود، این رویداد پس از ۱ ثانیه ارسال خواهد شد.
در اینجا چیزی است که در مثال شما امتحان کردم.
به من بگو اگر این کمک میکند
پاسخ شماره ۲
یک
debounceTime(250)به عنوان اولین پارامترfromEvent(...).pipe(...)اضافه کنیدهمانطور که قبلاً انجام میدادید،
breakpoint.nextرا درzone.run(..)قرار دهید و همچنین همان روشrunOutsideAngularرا حفظ کنید
تشخیص تغییر بعد از هر دوره ۲۵۰ میلیثانیه اجرا خواهد شد، همان چیزی که شما به دنبالش هستید - تجربه کاربری خوب بهعلاوه تشخیص تغییر محدود/کم
