现在可以传递一个 observable,这是扩展库的好方法。 但是,它有点受限制,因为用户无法以简单的方式访问图像。
最常见的问题之一是当用户不使用窗口滚动或使用添加额外滚动层的 3 部分库(例如离子、ng 材料设计等)时,有时很难找到找出实际滚动的元素。 解决此问题的一种方法可能是使用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
传递一个默认的 Observable :
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 等。 大多数问题都可以通过其他方式解决,但如果我们可以在创建 observable 时为用户提供更大的灵活性,那就太好了。
你怎么看@sapierens ,@rimlin?
@tjoskar ,据我所知,您想通过提供函数作为scrollObservable
选项来增强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
scrollObservable
,这将返回 Observable,它负责发出图像加载事件? 如果是这样,我认为这是一个很酷的主意!但我认为最好使用对象而不是枚举参数: