测试:路由切换下页面的执行

277 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情

前言

在之前的篇幅中我们讲到了原生页面和React路由在历史切换导致滚动条的行为变换。

结合之前的实践,这次我们想要探讨的是如何让react路由切换像原生页面切换一样符合逻辑与直觉。

实际上,并非react路由会出现这种情况,基于history下的dom切换都会有这种情况,而之前的实践就是为了处理这种情况。

前进后退下的页面调用

在项目开始前,我们基于v5路由的工程下有这样几个页面:

import {BrowserRouter as Router,Route,Switch,Link} from "react-router-dom"
import Home from "./components/Home"
import Users from "./components/User";

function Index(){
  return <>
   <Link to='/home'>home</Link>
   <Link to='/users'>users</Link>
  </>
}

function App() {
  return (
    <div className="App">
      <Router>
        <Switch>
        <Route path='/' component={Index} exact></Route>
        <Route path='/home' component={Home} exact></Route>
        <Route path="/users" component={Users} exact></Route>
        </Switch>
      </Router>
    </div>
  );
}

export default App;

//主页面
import { useState } from "react"
import { NavLink } from "react-router-dom"
const Home = () => {
    const [display, setDisplay] = useState(true)

    return <>
        {
            display ? (<>
                <div style={{
                    width: '500px',
                    background: 'red',
                    height: "400vh",
                    display: display ? 'block' : 'none'
                }}>

                </div>

                <NavLink
                    to="/users"
                >
                    user
                </NavLink>

                <div style={{

                    width: '500px',
                    background: 'red',
                    height: "400vh",
                    display: display ? 'block' : 'none'
                }}>

                </div>
            </>) : null
        }
    </>
}

export default Home

home.png

import { useEffect } from "react"
import { NavLink } from "react-router-dom"
function Users() {
  console.log("run")
  useEffect(() => {
    console.log("effect start")
  }, [])
  return <>
    <div style={{
      width: '500px',
      background: '#009c9c',
      height: "30vh"
    }}>

      <NavLink
        to="/home"
      >
        home
      </NavLink>
    </div>
    <NavLink
      to="/users"
    >
      user
    </NavLink>

    <div style={{
      width: '500px',
      background: 'green',
      height: "30vh"
    }}>


    </div>
  </>
}
export default Users

当我们点击跳转到/home页面,下滑跳转到/user页面。观察控制台输出:

home1.png

users.png 此时控制台的输出证明了useEffect执行了。 当我们回退页面,useEffect并没有执行。

home2.png 再次进入,useEffect再次执行:

users1.png

基于现象我们可以初步得出结论: 当路由再次进入时,当前useEffect会再次执行,组件内部会运行。而return的dom节点是否渲染则是根据内部的diff结果去处理。

回退页面滚动位置的复原

在上面的前进后退处理中,我们能看到滚动条的复原,结合之前的测试,我们是基于会退页面存在滚动高度而处理的,当我们回退的页面初始高度没有滚动条呢?

通过模拟数据请求延迟页面渲染,我们对homo组件进行如下处理:

import { useState,useEffect } from "react"
import { NavLink } from "react-router-dom"
const Home = () => {
    const [display, setDisplay] = useState(false)

    useEffect(() => {
     const timer =  setTimeout(()=>{
        setDisplay(true)
      },1000)
    
      return () => {
        clearInterval(timer)
      }
    }, [])
    

    return <>
        {
            display ? (<>
                <div style={{
                    width: '500px',
                    background: 'red',
                    height: "400vh",
                    display: display ? 'block' : 'none'
                }}>

                </div>

                <NavLink
                    to="/users"
                >
                    user
                </NavLink>

                <div style={{

                    width: '500px',
                    background: 'red',
                    height: "400vh",
                    display: display ? 'block' : 'none'
                }}>

                </div>
            </>) : null
        }
    </>
}

export default Home

我们先在home组件下滑到中间位置,然后点击跳转。

home3.png

users2.png

接着再次回退,我们期待着页面能够复原滚动条位置,然而当数据1s请求后,数据渲染dom,此时滚动条置顶了。

home4.png

结合之前文章的测试,我们初步了解到置顶的原因是因为初始页面并不存在滚动条。然而这种现象在常见的前端路由模式下依旧存在。

小结

  • 历史记录的前进回退中,组件在进入时会重新执行。
  • 初始页面是否有滚动高度决定了回退的页面是否能够复原滚动条。