问题描述
在我的网络应用中,我尝试设置滚动事件的div高度,以产生UI效果和视差, 当我滚动到顶部时,Div会变大;当我滚动到底部页面时,Div会变小,以获得视差效果。
我使用 @HostListener('window:scroll',['$ event'])来触发滚动,但它的工作却很不稳定,带有冻结帧,并具有随机延迟。
有人想到了为什么会有那么多的越野车吗?还是角度库可以通过性能优化做到这一点?
component.html:
<div id="header" class="header" >
<div class="coverBackgroundGradiantUp"> </div>
<div class="coverBackgroundGradiantDown">
</div>
</div>
<div id="panel" class="panel" (scroll)="scrollHandler($event)">
{...bodypage...}
</div>
component.ts:
export class ProfilComponent implements OnInit {
constructor() {
}
ngOnInit(): void {
}
@HostListener('window:scroll',['$event'])
scrollHandler(event) {
console.log(window.pageYOffset)
const offset = window.pageYOffset
if (offset < -1) {
document.getElementById("headerHeight").style.width = String((100 - offset/6)+ "%");
document.getElementById("headerHeight").style.height = String( 151 - offset + "px");
} else if (offset < 151) {
document.getElementById("headerHeight").style.height = String( 151 - offset + "px");
} else if (offset > 151) {
document.getElementById("headerHeight").style.height = String(0 + "px");
}
}
component.scss:
.header{
position: fixed;
display: flex;
flex-direction: column-reverse;
background-image: url("../../../../../assets/exempleCover.png");
background-size: cover;
background-repeat: no-repeat;
width: 100%;
height: 151px;
top: 59px;
background-color: red;
}
......
.panel{
position: relative;
top: 0;
width: auto;
margin-top: 146px;
z-index: 2;
}
解决方法
当您订阅类似事件时,每次回调执行后(每次触发DOM事件并执行回调),角度运行都会发生变化检测。您需要在角度区域外手动订阅DOM事件。
最简单的方法是:
将NgZone
注入您的组件:
constuctor(private readonly ngZone: NgZone) { }
通过本机浏览器api订阅ngOnInit()
中的滚动事件(也可以使用Renderer2
):
this.zone.runOutsideAngular(() => {
window.addEventListener('scroll',this.scrollHandler);
});
不要忘记退订ngOnDestroy()
中的事件:
window.removeEventListener('scroll',this.scrollHandler);
将scrollHandler
函数更改为lambda格式,以绑定上下文并将来可以退订:
scrollHandler = (event) => {
console.log(window.pageYOffset);
const offset = window.pageYOffset;
...
}
我在编辑器中编写了代码,所以可能会有一些错字。
,非常感谢阿米尔,
不幸的是,当我尝试使用renderer2时出现错误:
我有zone-evergreen.js:171未捕获的TypeError:无法读取未定义的属性'setAttribute',因为此面板未定义。
export class ProfilComponent implements OnInit,AfterViewInit {
***@ViewChildren('panel') panel: ElementRef;***
constructor(private readonly ngZone: NgZone,private renderer: Renderer2){ }
ngOnInit(): void {
this.ngZone.runOutsideAngular(() => {
window.addEventListener('scroll',this.scrollHandler);
});
}
ngAfterViewInit() {
console.log(this.panel);
}
scrollHandler(event) {
**console.log(this.panel)**
const offset = window.pageYOffset
**this.renderer.setAttribute(this.panel.nativeElement,"id","panel")**;
// if (offset < -1) {
// document.getElementById("headerHeight").style.width = String((100 - offset/6)+ "%");
//
// document.getElementById("headerHeight").style.height = String( 151 - offset + "px");
// } else if (offset < 151) {
// document.getElementById("headerHeight").style.height = String( 151 - offset + "px");
// } else if (offset > 151) {
// document.getElementById("headerHeight").style.height = String(0 + "px");
// }
}