描述:
当我们是需求是返回页面时要保持页面在离开时的样子,这里会有两个方面的考虑,一个是路由一定要设置复用策略,然后发现当页面有列表的时候,那就肯定有滚动条,当离开页面前操作了列表滚动到了若干页的随机位置,当返回的时候即使复用路由策略生效,但是发现列表会自动滚到最顶部位置,也就是说列表位置变了
通过以上情况要实现返回页面保持原状态
1.路由复用,不重新加载,不走重建销毁的这个过程
2.解决列表list不会保持到原来浏览位置
解决路由复用策略问题
前面有专门针对路由策略做过笔记,实现angular路由复用策略
这里就不过多赘述了
熟悉三大家族
提到滚动该条很容易想到关于滚动条scroll相关的属性,scroll家族有4个属性,分别为scrollWidth、scrollHeight、scrollLeft、scrollTop,下面回忆复习一下相关含义
1、offset偏移量
有以下常用属性
offsetWidth/offsetHeight:表示元素盒子的宽度和高度,包含border和padding ;
offsetLeft/offsetRight/offsetTop:表示是外边距,元素距离其他元素多少距离
offsetParent:表示获取父元素,如果父元素有用positon样式属性定位,那么获取的就是最近的父元素,如果没有用positon样式属性的,那么获取的是body
parentNode:获取的是最近父元素。
以上属性注意点
- 获取到的值是一个number类型,不带单位
- 获取的宽高包含border和padding
- 只能读取,不能设置
2、client偏移量
clientWidth/clientHieght:元素的可是区域的宽高,包括内边距padding,不包括border;
clientLeft/clientTop:记录的是元素的border的距离
注意:
*只读属性,不可修改
3、scroll偏移量
scrollTop/scrollLeft:元素划出去的距离;
scrollWidht/scrollHeight:子元素的宽高
注意:
*scrollWidth/scrollHeight:是只读属性,不可编辑的
- scrollTop/scrollLeft: 是可以编辑赋值的
以上熟悉了一些属性,接下来的我们要使用的属性是scoll家族
解决返回时滚动条位置发生变化问题
如上图所示,返回时,我们A页面的参数count为10,说明返回时,路由复用策略生效,页面并没有调用ngOninit()初始化,但是滚动条却默认回到最初的位置,查询了很多有关angular的特性,并没有针对路由复用时滚动条变化相关的解决办法,那这里索性用最原生的scroll属性来控制列表list的滚动条位置,打算这样做,
1.页面中监听滚动元素,当列表滚动时,把滚动的距离保存下来,也就是scrollTop属性值
2.当页面返回时,我们再读取先前保存下来的scrollTop,然后赋值给元素
以上是解决返回页面保持滚动条不变的解决思路
import { GlobalSubscriptionService } from './../../services/global-subscription.service';
import { Router } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { Component, OnInit, ViewChild, ElementRef, Renderer2, AfterViewInit } from '@angular/core';
@Component({
selector: 'app-route-strategy',
templateUrl: './route-strategy.component.html',
styleUrls: ['./route-strategy.component.scss']
})
export class RouteStrategyComponent implements OnInit, AfterViewInit {
@ViewChild('content', { static: true }) content: ElementRef | any;
public index: number = 0;
constructor(
private $http: HttpClient,
private $router: Router,
private $globalSub: GlobalSubscriptionService,
private renderer: Renderer2
) { }
ngOnInit(): void {
/**返回时ngOnInit是不会重新加载的,所以我们这里要用到路由Router的订阅,路由进来时进行相关操作*/
this.$router.events.subscribe(res => {
let scrollTop = localStorage.getItem('list-scroll') || 0;
this.content.nativeElement.scrollTop = scrollTop;
})
}
ngAfterViewInit(): void {
/**用Renderer2中方法的监听元素*/
this.renderer.listen(this.content.nativeElement, 'scroll', res => {
localStorage.setItem('list-scroll', res.target.scrollTop);
})
}
public onAdd(): void {
this.index++;
}
public onJump(): void {
this.$globalSub.$routeIsReuse.next({ field: `/route-strategy/route-strategy-first`, value: false });
this.$router.navigate(['/route-strategy/route-strategy-first'])
}
}
此时不仅页面没有重新加载,连列表list的滚动条位置也没有发生变化,这里用了Renderer2中的listen方法监听元素的scroll事件,这是官方推荐的用法,当list滑动时,先把scollTop存浏览器缓存,再次进入页面时,需要在ngOninit中订阅一下路由,因为此时的页面不会重新加载任何东西,只有订阅才可以进行相关操作,此时去获取缓存中的scrollTop,并且对元素进行设置。
总结
1.先弄清楚angular路由复用策略机制,进行相应的配置,这个配置是很灵活的,根据需求配置
2.通过原生的scrollTop属性来控制列表滑动位置,这个是要手动设置,先存再设置