react移动端项目初始化之底部导航被输入法顶起来

394 阅读2分钟

问题描述

移动端页面, 底部导航会被输入法顶起来

如图所示:

image.png

解决方案1

在底部导航组件里,监听window resize事件。如果页面高度发生了变化,那么就隐藏底部导航组件

效果

image.png

核心代码如下

//页面最初实际的高度
const [clientHeight, setClientHeight] = useState(null)
//页面变化后的高度
const [showHeight, setShowHeight] = useState(null)

useEffect(() => {
    //第一次加载底部导航, 获取页面的最初实际高度, 设置clientHeight的值
    setClientHeight(document.documentElement.clientHeight)
    setShowHeight(document.documentElement.clientHeight)

    window.onresize = () => {
        return (() => {
            //页面高度变化后, 设置showHeight的值
            setShowHeight(document.body.clientHeight)
        })()
    }

    return () => {
        window.onresize = () => {
        }
    }
}, [])

if (showHeight && clientHeight && showHeight < (clientHeight - 10)) {
    //如果页面变化后的高度 小于 最初的高度, 那么返回一个空页面
    return <div></div>
}

页面底部导航组件完整代码如下:

import {TabBar} from "antd-mobile";
import {useLocation, useNavigate} from "react-router";
import {useEffect, useState} from "react";

const Bottom = () => {
    const navigate = useNavigate()
    const location = useLocation()
    const {pathname} = location

    //页面最初实际的高度
    const [clientHeight, setClientHeight] = useState(null)
    //页面变化后的高度
    const [showHeight, setShowHeight] = useState(null)


    useEffect(() => {
        //第一次加载底部导航, 获取页面的最初实际高度, 设置clientHeight的值
        setClientHeight(document.documentElement.clientHeight)
        setShowHeight(document.documentElement.clientHeight)

        window.onresize = () => {
            return (() => {
                //页面高度变化后, 设置showHeight的值
                setShowHeight(document.body.clientHeight)
            })()
        }

        return () => {
            window.onresize = () => {
            }
        }
    }, [])

    const setRouteActive = (value) => {
        navigate(value)
    }

    const tabs = [
        {
            key: '/item-list',
            title: '首页',
            // icon: <AppOutline />,
        },
        {
            key: '/todo',
            title: '我的待办',
            // icon: <UnorderedListOutline />,
        },
        {
            key: '/message',
            title: '我的消息',
            // icon: <MessageOutline />,
        },
        {
            key: '/me',
            title: '个人中心',
            // icon: <UserOutline />,
        },
    ]

    if (showHeight && clientHeight && showHeight < (clientHeight - 10)) {
        //如果页面变化后的高度 小于 最初的高度, 那么返回一个空页面
        return <div></div>
    }

    return (
        <TabBar activeKey={pathname} onChange={value => setRouteActive(value)}>
            {tabs.map(item => (
                <TabBar.Item key={item.key} /*icon={item.icon}*/ title={item.title}/>
            ))}
        </TabBar>
    )
}

export default Bottom

解决方案2

设置viewport的height为初始页面的默认高度


useEffect(() => {
  //设置viewport的height为初始页面的默认高度
  let view = document.querySelector('meta[name="viewport"]');
  view.setAttribute('content', `height=${document.documentElement.clientHeight},width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no`)
},[])

同时分享一个

如果输入框在页面下面的位置,键盘弹起后,会遮挡住要输入的区域,只有开始输入的时候才会滚动到输入的位置,用户体验非常不好。

解决方案

window.onresize = () => {
    //如果输入框在页面下面的位置,键盘弹起后,会遮挡住要输入的区域,只有开始输入的时候才会滚动到输入的位置,用户体验非常不好。
    if (document.activeElement.tagName == "INPUT" || document.activeElement.tagName == "TEXTAREA") {
        window.setTimeout(function () {
            document.activeElement.scrollIntoViewIfNeeded();
        }, 0);
    }

    return (() => {
        //页面高度变化后, 设置showHeight的值
        setShowHeight(document.body.clientHeight)
    })()
}