Прямо сейчас можно передать наблюдаемое, что является отличным способом расширить библиотеку. Однако он немного ограничен, поскольку пользователи не могут получить доступ к изображению простым способом.
Одна из наиболее распространенных проблем - это когда пользователь не использует окно для прокрутки или использует библиотеку из 3 частей, которая добавляет дополнительные слои прокрутки (например, ionic, ng material design и т. Д.), И иногда бывает трудно найти какой элемент на самом деле прокручивается. Один из способов решить эту проблему - использовать Intersection Observer
(что также может повысить производительность). Например.
@Component({
selector: 'intersection-observer',
template: `<img #img [defaultImage]="defaultImage" [lazyLoad]="image" [scrollObservable]="subject">`,
})
export class IntersectionObserverComponent {
@ViewChild('img') img;
subject = new Subject();
defaultImage = 'https://www.placecage.com/1000/1000';
image = 'https://images.unsplash.com/photo-1467932760935-519284fc87fa?dpr=2&auto=compress,format&fit=crop&w=1199&h=800&q=80';
ngAfterViewInit() {
const config = {
rootMargin: '50px 50px',
threshold: 0.01
};
function onIntersection(entries) {
entries.forEach(entry => {
if (entry.intersectionRatio > 0) {
observer.unobserve(entry.target);
this.subject.next();
}
});
}
const observer = new IntersectionObserver(onIntersection, config);
observer.observe(this.img.nativeElement);
}
}
Однако это довольно громоздко.
Что мы можем сделать, так это принять функцию как scrollObservable
, что-то вроде:
if (!this.scrollObservable) {
const windowTarget = isWindowDefined() ? window : undefined;
scrollObservable = getScrollListener(this.scrollTarget || windowTarget);
} else if (typeof this.scrollObservable === 'function') {
scrollObservable = this.scrollObservable(image, offset) // and maybe more
} else {
scrollObservable = this.scrollObservable.startWith('');
}
Мы не можем переписать приведенный выше компонент на:
@Component({
selector: 'intersection-observer',
template: `<img [defaultImage]="defaultImage" [lazyLoad]="image"
[scrollObservable]="startLazyload" offest="50">`,
})
export class IntersectionObserverComponent {
defaultImage = 'https://www.placecage.com/1000/1000';
image = 'https://images.unsplash.com/photo-1467932760935-519284fc87fa?dpr=2&auto=compress,format&fit=crop&w=1199&h=800&q=80';
startLazyload(image, offset) {
Observable.create(observer => {
const intersectionObserver = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.intersectionRatio > 0) {
observer.next();
}
});
}, {
rootMargin: offset ? `${offset}px` : undefined,
threshold: 0.01
});
intersectionObserver.observe(image);
return () => observer.unobserve(image);
});
}
}
Лучше, но все же немного шумно, особенно когда пользователь хочет использовать IntersectionObserver
для всех изображений.
Способ решить эту проблему может заключаться в передаче наблюдаемого по умолчанию в NgModule
:
import { intersectionObserverLazyLoad } from 'some-place';
@NgModule({
declarations: [ AppComponent ],
imports: [ BrowserModule, lazyLoadImage({
observable: intersectionObserverLazyLoad
})],
bootstrap: [ AppComponent ]
})
export class MyAppModule {}
Мы не можем переписать приведенный выше компонент так:
@Component({
selector: 'intersection-observer',
template: `<img [defaultImage]="defaultImage" [lazyLoad]="image" offest="50">`,
})
export class IntersectionObserverComponent {
defaultImage = 'https://www.placecage.com/1000/1000';
image = 'https://images.unsplash.com/photo-1467932760935-519284fc87fa?dpr=2&auto=compress,format&fit=crop&w=1199&h=800&q=80';
}
Возможность передавать функции по умолчанию в NgModule также может открыть двери для создания пользовательских функций для isVisible
и loadImage
но это позже.
Решил бы: # 287, # 195, # 286, # 285, # 275, # 259 и другие. Большинство проблем решаются другими способами, но было бы неплохо, если бы мы могли дать пользователю больше гибкости при создании наблюдаемого.
Как вы думаете, @sapierens , @rimlin?
@tjoskar, насколько я понимаю, вы хотите улучшить scrollObservable
, предоставив функцию в качестве опции для scrollObservable
, которая вернет Observable, который отвечает за создание события загрузки изображения? Если это так, я думаю, это действительно крутая идея!
Но я думаю, что лучше использовать объект вместо перечисления аргументов:
...
} else if (typeof this.scrollObservable === 'function') {
scrollObservable = this.scrollObservable({
image,
offset
});
} else {
...
предоставить функцию в качестве опции для scrollObservable, которая вернет Observable, который отвечает за генерирование события загрузки изображения
Правильно, я могу также захотеть переименовать scrollObservable
но это было бы критическим изменением.
я думаю, что лучше использовать объект вместо перечисления аргументов
Дать согласие!
Я думаю, что это хорошая идея, особенно передача наблюдателя по умолчанию.
я думаю, что лучше использовать объект вместо перечисления аргументов
Я тоже согласен с этим.
Исправлено в # 365 и в версии 2.1.0
Самый полезный комментарий
@tjoskar, насколько я понимаю, вы хотите улучшить
scrollObservable
, предоставив функцию в качестве опции дляscrollObservable
, которая вернет Observable, который отвечает за создание события загрузки изображения? Если это так, я думаю, это действительно крутая идея!Но я думаю, что лучше использовать объект вместо перечисления аргументов: