likes
comments
collection
share

ScrollView固定高度遇到的问题

作者站长头像
站长
· 阅读数 37

「时光不负,创作不停,本文正在参加2021年终总结征文大赛

楼主总结了很多不同case下设置ScrollView高度的方法

相信很多小伙伴使用ScrollView都碰到过设置它的高度问题,特别烦人, display:flex,flex:1,根本不生效。

必须要给一个死的高度,可有的时候根本不确定这个高度是多少

ScrollView固定高度遇到的问题

比方说要让图中蓝色区域滚动,计算dom节点的top,从而高度赋值

通过getSystemInfo api之类的获取到设备信息中的windowHeight可使用窗口高度,然后再获取到蓝色区域的节点top值select(className).boundingClientRect,具体api看各个框架 然后相减就可以了windowHeight - vnodeTop,得到的值使用promise resolve回去,

<ScrollView
    scrollY
    style={`height: ${hg}px`}
>

设置就可以了,如果红色区域异步加载或者加载过慢,导致初始化时蓝色区域top获取不准确就加个setTimerout

useEffect(() => {
    const timer = setTimeout(() => {
        scrollViewHg('.class-name').then(res => {
            setHg(res);
            clearTimeout(timer);
        });
    }, 100);

    return () => {
        clearTimeout(timer);
    };
}, []);

再如果,掌控不好延时器的毫秒数,那就另一种

const hg = useRef(0);
useEffect(() => {
    scrollViewHg('.class-name').then(res => {
        hg.current = res;
    });
});

style={`height: ${hg.current}px`}

每次render都会更新scrollView的高度,避免之后不需要更新了,可以加一些操作,记录进入页面的时间戳,与render时的时间戳对比,比方说过了5秒钟,则不再需要更新scrollView的高度,改加载的都加载完了,注意useEffect中不要执行render的操作,比如setState,否则会引起死循环

const timer = useRef(new Date());
useEffect =>
const curTimer = new Date();
if(curTimer - timer < 5000) {执行副作用,更新节点位置}

class组件则在componentDidUpdate生命周期调用,每次render时更新节点位置,同理,内部不要执行render的操作

componentDidUpdate() {
    scrollViewHg('.class-name').then(res => {
        hg.current = res;
    });
}

是不是5秒内会高频更新节点位置不太好,要不然加个防抖?要是用户打开弹窗,高频更新还没完毕,岂不是高度为0. 加个节流?又加定时器,可别了吧,啥也不加挺好的 可如果不加定时器,组件内挂载一个全局变量,hook用useRef

//this.timer = new Date();
//componentDidUpdate() {
    //const curTimer = new Date();
    //if (curTimer - timer > 200) {
        //this.timer = curTimer;
        //scrollViewHg('.class-name').then(res => {
            //hg.current = res;
        //});
    //}
//}

这样虽然没用定时器,但是问题就来了,如果下次更新与上次更新间隔小于200毫秒,那将会漏掉更新节点

啥也不加了,高频更新挺好的,多准确


敲黑板,重点来了,说一下楼主当初遇到的问题

楼主当初用的框架是Taro2,h5和小程序多端开发, 小程序经常不兼容h5的写法,不知道是框架还是小程序开发者工具导致的

h5计算高度正常,小程序就不对了,反复定位是小程序使用了自定义导航栏,导致窗口高度不准确

**const** {windowHeight, statusBarHeight, navigationBarHeight, screenHeight} = await Taro.getSystemInfo();
const swanHeight = isSustom
    ? windowHeight + statusBarHeight + navigationBarHeight - vnodeTop
    : windowHeight - vnodeTop;

解决方法就是可使用窗口高度+状态栏高度+导航栏高度-节点高度

要是使用screenHeight屏幕高度就不用那么麻烦了?

主要是楼主当初根本没想到是自定义导航栏的问题,以为是该死的小程序编译问题,能把楼主搞崩溃的只有小程序编译,那些苦就随风而去吧,你我勉力前行。