react的生命週期函式

刘先生的爱心博客發表於2024-03-19

react的生命週期函式

1. react所有的生命週期函式

https://react.docschina.org/docs/react-component.html

掛載

當元件例項被建立並插入 DOM 中時,其生命週期呼叫順序如下:

  • constructor()

  • static getDerivedStateFromProps()

  • render()

  • componentDidMount()

更新

當元件的 props 或 state 發生變化時會觸發更新。元件更新的生命週期呼叫順序如下:

  • static getDerivedStateFromProps()

  • shouldComponentUpdate()

  • render()

  • getSnapshotBeforeUpdate()

  • componentDidUpdate()

解除安裝

當元件從 DOM 中移除時會呼叫如下方法:

  • componentWillUnmount()

2. 常用的生命週期方法

建立階段

constructor

作用: (1) 獲取props (2) 初始化state

render

作用:渲染元件到頁面中,無法獲取頁面中的DOM物件

componentDidMount()

(1) 元件已經掛載到頁面中 (2) 可以進行DOM操作,比如:獲取到元件內部的DOM物件 (3) 可以傳送請求獲取資料 (4) 可以透過 setState() 修改狀態的值 注意:在這裡修改狀態會重新渲染

執行和互動階段

componentDidUpdate(prevProps, prevState)

作用:元件已經被更新 引數:舊的屬性和狀態物件

解除安裝階段

componentWillUnmount()

元件解除安裝期間,只有一個函式,這個函式也有一個顯著的特點:元件一輩子只能執行一次 使用說明 只要元件不再被渲染到頁面中,那麼這個方法就會被呼叫( 渲染到頁面中 -> 不再渲染到頁面中 )

作用:在解除安裝元件的時候,執行清理工作,比如清除定時器

講解用案例程式碼

子元件

// 子元件
class Child extends Component {
  //構造方法
  constructor() {
    console.log('Child-constructor');
    super()
    this.state = {
      parentMsg: '父元件的資料'
    }
  }
  // 元件掛載後
  componentDidMount(){
    console.log('Child-componentDidMount');
  }
  // 是否應該更新元件
  shouldComponentUpdate(){
    console.log('Child-shouldComponentUpdate');
    return true
  }
  // 元件更新後
  componentDidUpdate(){
    console.log('Child-componentDidUpdate');
  }
  // 元件解除安裝前
  componentWillUnmount(){
    console.log('Child-componentWillUnmount');
  }
  //元件渲染
  render() {
    console.log('Child-render');
    return (
      <div>
        <p>子元件------------------{this.state.parentMsg}</p>
      </div>
    );
  }
}

父元件

// 父元件
class App extends Component {
  // 構造方法
  constructor() {
    console.log('App-constructor');
    super()
    this.state = {
      parentMsg: '父元件的資料'
    }
  }
  // 元件掛載後
  componentDidMount(){
    console.log('App-componentDidMount');
  }
  // 是否應該更新元件
  shouldComponentUpdate(){
    console.log('App-shouldComponentUpdate');
    return true
  }
  // 元件更新後
  componentDidUpdate(){
    console.log('App-componentDidUpdate');
  }
  // 元件解除安裝前
  componentWillUnmount(){
    console.log('App-componentWillUnmount');
  }
​
  change = ()=>{
    this.setState({
      parentMsg: '新的新的'
    })
  }
  //元件渲染
  render() {
    console.log('App-render');
    return (
      <div>
          <p>父元件-------------------{this.state.parentMsg}</p>
          <Child msg={this.state.parentMsg}></Child>
          <p><button onClick={this.change}>改變父元件的資料</button></p>
      </div>
    );
  }
}

react 路由v6使用

1. 安裝路由依賴包

npm i react-router-dom -S

2. 案例程式碼

import React from 'react
//引入路由中的各種API
import { 
    HashRouter,
    BrowserRouter,
    Routes, 
    Route,
    Navigate,
    Link,
    NavLink,
    Outlet
   } from 'react-router-dom'

// 引入路由相關元件
import Home from './Home'
import Cart from './Cart'
import My from './My'
import NotFound from './NotFound'
import FooterNav from './FooterNav'
import Tv  from './home/Tv'
import Ai  from './home/Ai'
import Login from './Login'

export default function App() {
    return (
        <BrowserRouter>
            <Routes>
                <Route path="/home" element={<Home></Home>}>
                    <Route path="tv" element={<Tv></Tv>}></Route>
                    <Route path="ai" element={<Ai></Ai>}></Route>
                </Route>
                <Route path="/cart" element={<Cart></Cart>}></Route>
                <Route path="/login" element={<Login></Login>}></Route>
                <Route path="/my" element={<My></My>}></Route>
                <Route path="/" element={<Navigate to="/home"></Navigate>}></Route>
                <Route path="*" element={<NotFound></NotFound>}></Route>
            </Routes>
            <FooterNav></FooterNav>
        </BrowserRouter>
    )
}

3. 路由API

3.1 BrowserRouter和HashRouter

  • 二者都是路由的包裹元素,設定路由模式

  • BrowserRouter是history模式, 生產版本需要後端進行相應的配置, 路徑前沒有'#',比較美觀

  • HashRouter是hash模式,路由前有'#'

3.2 Routes

路由配置的包裹元素,<Route>必須放在<Routes>中,不然報錯

3.3 Route

<Route path="/cart" element={<Cart></Cart>}></Route>

3.4 Navigate重定向

<Route path="/" element={<Navigate to="/home"></Navigate>}></Route>

3.5 Link和NavLink

<Link to="/movie" >電影</Link>
<NavLink to="/find" class="active">發現</NavLink>

4. 巢狀路由

4.1 定義巢狀路由

<Route path="/home" element={<Home></Home>}>
<Route path="tv" element={<Tv></Tv>}></Route>
<Route path="ai" element={<Ai></Ai>}></Route>
</Route>

4.2 預設路由

<Route path="/home" element={<Home></Home>}>
<Route index element={<Tv></Tv>}></Route>
<Route path="ai" element={<Ai></Ai>}></Route>
</Route>

4.3 Outlet定義二級路由出口

import React,{useState,useEffect} from 'react'
import style from './Home.css'
import { Outlet,NavLink,useNavigate} from 'react-router-dom'

export default function Home() {

    return (
        <div>
            <div className="header">
                <p><NavLink to="" >電視</NavLink></p>
                <p><NavLink to="ai" >智慧</NavLink></p>
            </div>
            <Outlet></Outlet>
        </div>
    )
}

5. 動態路由

5.1 動態路由

<Route path="/list/:id" element={<List></List>}></Route>

5.2 路由跳轉

<p><NavLink to="/list/5">列表</NavLink></p>

5.3 獲取動態路由引數

import { useParams } from 'react-router-dom';

...

const params = useParams()
console.log(params.id)  //5

6. React-router 的Hooks

import { useNavigate,useParams,useSearchParams,useLocation } from 'react-router-dom';

6.1 useNavigate

const navigate = useNavigate()

//跳轉到/my
navigate("/my")  

//跳轉到上一頁
navigate(-1)

//跳轉到/my,並替換當前歷史記錄
navigate("/my",{replace: true})

//攜帶引數
navigate("/my",{replace: true,state:{arr:[1,2,3]}})

6.2 useParams

動態路由

<Route path="/list/:id" element={<List></List>}></Route>
<p><NavLink to="/list/5">列表</NavLink></p>

const params = useParams()
console.log(params.id) //5

6.3 useSearchParams

import { useSearchParams } from 'react-router-dom';

// 當前路徑為 /foo?id=12
function Foo(){
    const [searchParams] = useSearchParams();
    console.log(searchParams.get('id')) // 12
    return (
        <div>foo</div>
    )
}

6.4 useLocation

  1. hash: ""

  2. key: "h8dnd0wk"

  3. pathname: "/list/5"

  4. search: ""

  5. state: null

6.4 案例程式碼

import { useNavigate,useParams,useLocation } from 'react-router-dom';
...
export default function List() {
    //用navigate實現程式設計式導航
    const navigate = useNavigate()
    //獲取動態路由的引數
    const params = useParams()
    //獲取url資訊
    const location = useLocation()

    const toUrl = ()=>{
        // navigate("/my")
        navigate("/my",{replace: true})
    }
    return (
        <div>
            list
            <hr />
            <button onClick={toUrl}>回到我的</button>
        </div>
    )
}

7. 仿小米App的路由配置

7.1 FooterNav.css

.footerNav {
    display: flex;
    justify-content: space-around;
    position: absolute;
    width: 100%;
    height: 60px;
    left: 0;
    bottom: 0;
    background-color: #aaa;
}
.footerNav .active{
    border: 1px solid #000;
    background-color: #f00;
}

7.2 FooterNav.js

import React from 'react'
import { Link, NavLink } from 'react-router-dom'
import './FooterNav.css'
export default function FooterNav() {
    return (
        <div className="footerNav">
            <p><NavLink to="/home">首頁</NavLink></p>
            <p><NavLink to="/cart">購物車</NavLink></p>
            <p><NavLink to="/my">我的</NavLink></p>
            <p><NavLink to="/list/5">列表</NavLink></p>
        </div>
    )
}

7.3 App.js

import React from 'react'
import { HashRouter,BrowserRouter,Routes, Route,Navigate,Link,NavLink,Outlet} from 'react-router-dom'
import Home from './Home'
import Cart from './Cart'
import My from './My'
import NotFound from './NotFound'
import FooterNav from './FooterNav'
import Tv  from './home/Tv'
import Ai  from './home/Ai'
import Login from './Login'
import isLogin from './util/token'
import List from './List'

export default function App() {
    return (
        <BrowserRouter>
            <Routes>
                <Route path="/home" element={<Home></Home>}>
                    <Route path="tv" element={<Tv></Tv>}></Route>
                    <Route path="ai" element={<Ai></Ai>}></Route>
                </Route>
                <Route path="/cart" element={isLogin() ?<Cart></Cart>:<Login></Login>}></Route>
                <Route path="/login" element={<Login></Login>}></Route>
                <Route path="/my" element={<My></My>}></Route>
                <Route path="/my" element={<My></My>}></Route>
                <Route path="/list" element={<List></List>}></Route>
                <Route path="/" element={<Navigate to="/home"></Navigate>}></Route>
                <Route path="*" element={<NotFound></NotFound>}></Route>
            </Routes>
            <FooterNav></FooterNav>
        </BrowserRouter>
    )
}

7.4 Home.css

.header {
    display: flex;
    justify-content: space-around;
}
.header .active {
    border: 1px solid #000;
}
.header .atdh {
    background-color: #f00;
}

7.5 Home.js

import React,{useState,useEffect} from 'react'
import style from './Home.css'
import { Outlet,NavLink,useNavigate} from 'react-router-dom'

export default function Home() {
    const navigate = useNavigate();
    useEffect(()=>{
        navigate('/home/tv')
    },[])// eslint-disable-line

    return (
        <div>
            <div className="header">
                <p><NavLink to="tv" >電視</NavLink></p>
                <p><NavLink to="ai" >智慧</NavLink></p>
            </div>
            <Outlet></Outlet>
        </div>
    )
}

8. useRoutes的使用

<Route path="/home" element={<Home></Home>}>
    <Route path="tv" element={<Tv></Tv>}></Route>
    <Route path="ai" element={<Ai></Ai>}></Route>
</Route>

在App.js中透過json資料實現路由配置

import React from 'react'
import { BrowserRouter as Router, Navigate, useRoutes } from 'react-router-dom'

import Home from './pages/Home'
import Category from './pages/Category'
import Phone from './pages/Category/Phone'
import NoteBook from './pages/Category/NoteBook'
import GoodsList from './pages/GoodsList'
import My from './pages/My'
import Detail from './pages/Detail'
import NotFound from './pages/NotFound'

const GetAllRoutes = () => {
    const routes = useRoutes([
        {
            path: '/',
            element: <Navigate to="/Home" />
        },
        {
            path: '/Home',
            element: <Home />
        },
        {
            path: '/Category',
            element: <Category />,
            children: [
                {
                      //預設路由
                    index: true,
                    element: <Phone />
                },
                {
                    path: 'NoteBook',
                    element: <NoteBook />
                }
            ]
        },
        {
            path: '/GoodsList',
            element: <GoodsList />
        },
        {
            path: '/My',
            element: <My />
        },
        {
            path: '/Detail/:id',
            element: <Detail />
        },
        {
            path: '/404',
            element: <NotFound />
        },
        {
            path: '*',
            element: <NotFound />
        }
    ])
    return routes;
}


export default function App() {
    return (
        <Router>
            <GetAllRoutes />
        </Router>
    )
}

9. 路由懶載入和鑑權

lazy()路由懶載入

import {lazy} from 'react'
const Later = lazy(() => import('./Later'));

Suspense元件

import  {  lazy, Suspense } from 'react';
const Later = lazy(() => import('./Later'));

export default function  App {
   return (
     <div> 
       <Suspense fallback={<div>loading...</div>}>
         <Later />  
       </Suspense>
     </div>
   );
}

案例涉及檔案列表

src/routes/index.js

src/routes/config.js

src/routes/privateRoute.js

案例程式碼

src/routes/privateRoute.js

/**
 *  PrivateRoute使用方式
 *  <PrivateRoute element={<Cart>} tag="許可權"> </PrivateRoute>
 *  props: {element:, tag: }
 */
import { Navigate } from "react-router-dom";
const PrivateRoute = props => {
  const isLogin = localStorage.getItem("token")
  return isLogin ? (
    (props.element)
  ) : (
    <Navigate to="/login"></Navigate>
  );
};

export default PrivateRoute;

src/routes/config.js

import PrivateRoute from './privateRoute';
import { Suspense } from 'react';
const WrapperRouteComponent = ({ titleId, auth, ...props }) => {
    if (titleId) {
        document.title = titleId
    }
    return (
        <Suspense fallback={<div>loading...</div>}>
            {auth ? <PrivateRoute {...props} /> : (props.element)}
        </Suspense>
    )
};
export default WrapperRouteComponent;

src/routes/index.js

import { lazy } from 'react';
import Home from '../Home';
import WrapperRouteComponent from './config';
import { useRoutes, Navigate } from 'react-router-dom';

const NotFound = lazy(() => import(/* webpackChunkName: "404'"*/ '../NotFound'));
const Ai = lazy(() => import(/* webpackChunkName: "ai'"*/ '../home/Ai'));
const Tv = lazy(() => import(/* webpackChunkName: "tv'"*/ '../home/Tv'));
const Cart = lazy(() => import(/* webpackChunkName: "Cart'"*/ '../Cart'));
const My = lazy(() => import(/* webpackChunkName: "My'"*/ '../My'));
const List = lazy(() => import(/* webpackChunkName: "List'"*/ '../List'));
const Detail = lazy(() => import(/* webpackChunkName: "Detail'"*/ '../Detail'));
const Login = lazy(() => import(/* webpackChunkName: "Login'"*/ '../Login'));

const routeList = [
    {
        path: '/',
        element: <Navigate to="/home" />
    },
    {
        path: '/home',
        // element: <Home />,
        element: <WrapperRouteComponent element={<Home />} titleId="首頁" />,
        children: [
            {
                path: 'ai',
                element: <WrapperRouteComponent element={<Ai />} titleId="ai" />,
            },
            {
                path: 'tv',
                element: <WrapperRouteComponent element={<Tv />} titleId="tv" />,
            }
        ]
    },
    {
        path: '/cart',
        element: <WrapperRouteComponent element={<Cart />} titleId="Cart" auth={true}/>,

    },
    {
        path: '/my',
        element: <WrapperRouteComponent element={<My />} titleId="My" />
    },
    {
        path: '/list',
        element: <WrapperRouteComponent element={<List />} titleId="List" />
    },
    {
        path: '/detail/:id/:type',
        element: <WrapperRouteComponent element={<Detail />} titleId="Detail" />
    },
    {
        path: '/login',
        element: <WrapperRouteComponent element={<Login />} titleId="Login" />
    },
    {
        path: '/404',
        element: <NotFound />
    },
    {
        path: '*',
        element: <NotFound />
    }
]
const RenderRouter = () => {
    const element = useRoutes(routeList);
    return element;
};

export default RenderRouter;

App.js

import React from 'react'
import "./App.css"
//引入路由中的各種API
import {
  BrowserRouter as Router,
} from 'react-router-dom'

import RenderRouter  from './routes'
import TabBar from './TabBar'


export default function App() {
  return (
    <div className="app">
      <Router>
         <RenderRouter></RenderRouter>
         <TabBar></TabBar>
      </Router>
    </div>
  )
}

相關文章