zoukankan      html  css  js  c++  java
  • react-8 路由

    路由本质上是操作的history的地址的历史记录

    SPA应用(single page web application)

    1. 整个应用只有一个完整的页面
    2. 点击页面的链接不会刷新页面,只会做页面的局部更新
    3. 数据都需要通过ajax请求获取,并在前端异步展现

    mark

    单页面用显示隐藏其实也可以实现,但是没人会用,因为页面初始化时所有的标签都会渲染,会增加巨大的开销。

    理解react路由

    多页面网站是通过超链接来实现页面的切换的, 所有每次点击超链接时浏览器都需要刷新请求新的页面,而单页面应用程序主要通过路由来实现内容的切换,在react当中也就是切换组件

    那如何实现组件的切换呢?

    react路由是通过一种特殊的链接, 点击时会修改浏览器地址栏中的地址,但是浏览器是会忽略掉这次变化所以界面不会被跳转,但是在路由会监听到地址(path) 的变化从而根据不同的地址渲染出来不同的组件(component)

    相当于给组件打标识(一种特殊的链接),并根据不同的情况进行''条件渲染''。

    react route

    目前,官方同时维护2.x和4.x两个版本,React 16及以上版本只支持router4 x版本

    react Router4.0 (以下简称RR4)它遵循React的设计理念, 即万物皆组件。所以RR4只是一堆提供了导航功能的组件(还有若干对象和方法),具有声明式 (引入即用),可组合性的特点。

    安装

    cnpm install react-router-dom -D
    

    三大核心内容

    • 路由器组件
    • 路由匹配组件
    • 导航组件

    路由器组件

    作用:根据地址栏的变化引导显示相应组件,一般会包裹在最外层

    最常用的路由器分为两种:<BrowserRouter> <HashRouter>

    1、<Router>

    如果我们希望页面中某个部分的内容需要根据URL来动态显示,需要用到Router组件,该组件是一个容器组件,只需要用它包裹URL对应的根组件即可

    Router是所有路由组件共用的底层接口,一般我们的应用并不会使用这个接口, 而是使用高级的路由(用来是为了监听)

    2、<BrowserRouter>

    <BrowserRouter>:使用HTML5提供的history API来保持UI和URL的同步;(因此可以使用前进后退)

    3、<HashRouter>

    使用URL的hash (例如: window.location.hash)来保持UI和URL的同步 )(基本不用)

    4、<MemoryRouter>

    能在内存保存你“URL"的历史纪录(并没有对地址栏读写);

    5.<StaticRouter>

    从不会改变地址;

    :这里<Router>组件下只允许存在一个子元素,如存在多个则会报错。

    路由匹配组件

    作用:注册路由

    (1)<Route>

    Route组件主要的作用就是当location匹配路由的path时, 渲染某些UI。
    (2)<Route>组件有如下属性

    • path (sting) :路由匹配路径。(没有path属性的Route 总是会匹配) ;
    • component: 设置要显示的组件,该属性以props的方式传入
    • exact (bool) : exact 属性表示路由使用精确匹配模式,非exact模式下匹配所有以“开头的路由,一般都会设置,值可以省略
    <Route path="/about" component={About}></Route>
    <Route path="/home" component={Home}></Route>
    

    导航组件

    作用:替换a标签。点击时,实现地址栏地址的改变

    点击时,其实react-router-dom拦截了a标签的默认动作,然后根据所有使用的路由模式进行处理,改变了url但不会发送请求,同时根据router中设置的对应组件来进行显示。

    导航组件有两类:Link和NavLink

    NavLink是对Link的一个特定版本,作用是当匹配到当前的url时会给已渲染的 元素添加样式参数。

    使用语法:

    <li>  <NavLink to="/about"  activeClassName="navActive"> About</NavLink> </li>
    <li> <NavLink to="/home"  activeClassName="navActive"> Home</NavLink> </li>
    

    当点击当前link时,会自动给当前标签加一个“navActive”的类。这时我们可以自定义该类的 css样式。

    switch

    一个路径匹配多个组件的时候,会用到switch。 (效率的优化)

    因为路由匹配到匹配到一个后还会继续向下匹配。(只匹配一个)

    使用:把route那switch包一下

     <Switch>
            <Route path="/about" component={About}></Route>
            <Route path="/home" component={Home}></Route>
      </Switch>
    

    精准匹配与模糊匹配

    <Link to="/home/a/b"></Link>
    
    <Route  path="/home" component={Nav}> </Route>
    

    上面可以匹配上。这是模糊匹配

    如果加上exact,会开启严格匹配,地址必须精准对应。

    注意:严格匹配不能随便开!有时开启会导致无法匹配二级路由。

    redirect 重定向

    重定向。当用户访问某界面时,该界面并不存在,此时用Redirect重定向,重新跳到一个我们自定义的组件里。

    写在注册路由最后位置,和router写在一起。

    <Switch>
        <Route path="/about" component={About}></Route>
        <Route path="/home" component={Home}></Route>
        <Redirect to="/about"  />
    </Switch>
    

    上面代码,在地址栏输入localhost:3000时,会重定向至/about

    一级路由练习

    组件结构:

    • about
    • home

    (1)定义两个组件

    (2)在app.js中进行Link的设置和路由的注册

    (3)在index.js中使用B

    about.jsx

    // home组件
    import React from "react";
    class About extends React.Component{
        render(){
            return(
                <div>
                    这是About的内容
                </div>
            )
        }
    }
    export default About
    
    

    home.jsx

    // home组件
    import React from "react";
    class Home extends React.Component{
        render(){
            return(
                <div>
                    这是Home的内容
                </div>
            )
        }
    }
    export default Home
    
    

    app.jsx

    
    import { Route, Switch,Redirect } from "react-router-dom";
    import React from "react";
    import MyNavLink from "./component/pages/MyNavLink/MyNavLink";
    
    // 引入组件
    import About from "./component/pages/about/about";
    import Home from "./component/pages/home/home";
    
    class App extends React.Component {
      render() {
        return (
          <div id="zz">
            <li>
              <MyNavLink to="/about">About </MyNavLink>
            </li>
    
            <li>
              <MyNavLink to="/home">Home</MyNavLink>
            </li>
    
    
            <Switch>
              <Route path="/about" component={About}></Route>
              <Route path="/home" component={Home}></Route>
              <Redirect to="/about"  />
            </Switch>
          </div>
        );
      }
    }
    
    export default App;
    
    

    index.js

    import React from "react";
    import ReactDOM from "react-dom";
    import { BrowserRouter, Route } from "react-router-dom";
    import App from './App'
    import "./index.css";
    
    ReactDOM.render(
    
     // BrowserRouter 组件法放在这个位置,是因为全局所有的路由都包起来,因为,不同的路由器之间不能通信
      <BrowserRouter>
        <App/>
      </BrowserRouter>,
      document.getElementById("root")
    );
    

    嵌套路由(二级路由)

    组件结构:在一级路由的基础上书写二级路由

    将About下设置两个子组件:aboutSon1、aboutSon2.(除了About,其他东西没动)

    然后再About组件中设置二级路由。

    路由匹配先从一级路由开始匹配

    点二级路由时,先匹配一级的about,然后再在一级的路由向下匹配/about/left

    注意此时不能加exact ,开启后,子路由就废了,因为不开始模糊匹配。

    模糊匹配:如果书写的路由多,则可以匹配到,如果少了就不行。

    例如若给的是/home/a/b,则先匹配到一级的home,这就算匹配上了,这就不会出错。

    about.jsx

    // about组件
    
    import React from "react";
    
    import AboutSon1 from "./aboutSon1/aboutSon1";
    import AboutSon2 from "./aboutSon2/aboutSon2";
    import { Route, NavLink ,Redirect} from "react-router-dom";
    
    class About extends React.Component {
      render() {
        return (
          <ul>
            <li>
             
              <NavLink to="/about/left" activeClassName="navActive">
                左边
              </NavLink>
            </li>
            <li>
           
              <NavLink to="/about/right" activeClassName="navActive">
                右边
              </NavLink>
            </li> 
                <Route path="/about/left" component={AboutSon1}></Route>
                <Route path="/about/right" component={AboutSon2}></Route>
                <Redirect to="/about/right"  />
          </ul>
        );
      }
    }
    
    export default About;
    
    

    aboutSon1.jsx

    import React, { Component } from "react";
    
    export default class AboutSon1 extends Component {
      render() {
        return <div className="about-left">这时about右边的内容</div>;
      }
    }
    

    aboutSon2.jsx

    import React, { Component } from "react";
    
    export default class AboutSon2 extends Component {
      render() {
        return <div className="about-right">这时about右边的内容</div>;
      }
    }
    
    

    路由传值

    param传值

    三步走:

    (1)路由时,携带参数

    (2)在子组件声明接受params参数

    (3)子组件取值

    传来的值毫无疑问是在props中,我们来看一下,他在什么位置。

    如图可知,在this.props.match.params;中。

    mark

    (1)传值

         <ul>
              {this.state.messages.map(message => {
                return (
                  <li key={message.id}>
                    //传值
                    <Link to={`/about/right/message/${message.id}/${message.title}`}> {message.title}</Link>
                  </li>
                );
              })}
            </ul>
    

    (2)声明接收

           {/*声明接受 */}
            <Route path="/about/right/message/:id/:title" component={ Details}/> 
    

    (3)取值

     const { id, title } = this.props.match.params;
    

    完整代码:

    message:

    import React, { Component } from "react";
    import { Route, Link } from "react-router-dom";
    
    import Details from "./details/details";
    
    export default class Message extends Component {
      state = {
        messages: [
          {
            id: "01",
            title: "title1"
          },
          {
            id: "02",
            title: "title2"
          },
          {
            id: "03",
            title: "title3"
          }
        ]
      };
    
      render() {
        return (
          <div>
            <ul>
              {this.state.messages.map(message => {
                return (
                  <li key={message.id}>
                    <Link to={`/about/right/message/${message.id}/${message.title}`}> {message.title}</Link>
                  </li>
                );
              })}
            </ul>
    
            <hr />
    
            {/*声明接受 */}
            <Route path="/about/right/message/:id/:title" component={ Details}/> 
         
          </div>
        );
      }
    }
    
    

    messageDetails:

    import React, { Component } from "react";
    
    export default class Details extends Component {
      state = {
        messageDetail: [
          {
            id: "01",
            content: "你好中国"
          },
          {
            id: "02",
            content: "你好南京"
          },
          {
            id: "03",
            content: "你好杭州"
          }
        ]
      };
      render() {
        console.log(this.props);
    
        const { id, title } = this.props.match.params;
        const content = this.state.messageDetail.find(value => {
          return value.id == id;
        });
    
        return (
          <li>
            <ul>
              <li>id:{id}</li>
              <li>title:{title}</li>
              <li> content:{content.content}</li>
            </ul>
          </li>
        );
      }
    }
    

    效果:

    mark

    mark

    有历史记录,replace没有历史记录。

    mark

    通过search传值:

    这个仅需两步走:

    (1)传值

    (2)子组件取值

    注:无需声明接收

    再看一下传过来的参数在什么位置 this.props.location.search

    mark

    引入一个库: import qs from "querystring";

    这个可转么做search类型的解析转化:

    两个方法:

    qs.parse() 将"id=01&title=title1"解析成 {id: "01", title: "title1"}

    qs.stringify():将 {id: "01", title: "title1"}解析成"id=01&title=title1"

    "id=01&title=title1"是encoded格式编码的字符串

    (1)传值

    <ul>
        {this.state.messages.map(message => {
            return (
                <li key={message.id}>
                    <Link to={`/about/right/message/details/?id=${message.id}&title=${message.title}`}> {message.title}</Link>
                </li>
            );
        })}
    </ul>
    

    (2)读取

        const { id, title } = qs.parse(search.slice(1));
    

    完整代码:

    message:

    import React, { Component } from "react";
    import { Route, Link } from "react-router-dom";
    
    import Details from "./details/details";
    
    export default class Message extends Component {
      state = {
        messages: [
          {
            id: "01",
            title: "title1"
          },
          {
            id: "02",
            title: "title2"
          },
          {
            id: "03",
            title: "title3"
          }
        ]
      };
    
      render() {
        return (
          <div>
            <ul>
              {this.state.messages.map(message => {
                return (
                  <li key={message.id}>
                    <Link to={`/about/right/message/details/?id=${message.id}&title=${message.title}`}> {message.title}</Link>
                  </li>
                );
              })}
            </ul>
    
            <hr />
    
            {/*声明接受 */}
            <Route path="/about/right/message/details" component={ Details}/> 
         
          </div>
        );
      }
    }
    
    

    messageDetails:

    import React, { Component } from "react";
    
    import qs from "querystring";
    
    export default class Details extends Component {
      state = {
        messageDetail: [
          {
            id: "01",
            content: "你好中国"
          },
          {
            id: "02",
            content: "你好南京"
          },
          {
            id: "03",
            content: "你好杭州"
          }
        ]
      };
      render() {
        console.log(this.props);
        // 接收search
        const { id, title } = qs.parse(search.slice(1));
        const result = this.state.messageDetail.find(value => {
          return value.id == id;
        });
    
        console.log(result)
        return (
          <li>
            <ul>
              <li>id:{id}</li>
              <li>title:{title}</li>
              <li> content:{result.content}</li>
            </ul>
          </li>
        );
      }
    }
    
    

    mark

    但只要页面刷新,数据就会丢失。

    通过state传值:

    这个需要两步走:

    (1)传值

    (2)读取

    也是无需声明接收

    老套路,看位置

    this.props.location.state

    mark

    (1)传值

            <ul>
              {this.state.messages.map(message => {
                return (
                  <li key={message.id}>
                    <Link to={ { pathname:'/about/right/message/details',state:{id:message.id,title:message.title}}}> {message.title}</Link>
                  </li>
                );
              })}
            </ul>
    

    (2)读取

       const { id, title } = this.props.location.state;
    

    完整代码:

    message:

    import React, { Component } from "react";
    import { Route, Link } from "react-router-dom";
    
    import Details from "./details/details";
    
    export default class Message extends Component {
      state = {
        messages: [
          {
            id: "01",
            title: "title1"
          },
          {
            id: "02",
            title: "title2"
          },
          {
            id: "03",
            title: "title3"
          }
        ]
      };
    
      render() {
        return (
          <div>
            <ul>
              {this.state.messages.map(message => {
                return (
                  <li key={message.id}>
                    {/* <Link to={`/about/right/message/details/?id=${message.id}&title=${message.title}`}> {message.title}</Link> */}
                    <Link to={ { pathname:'/about/right/message/details',state:{id:message.id,title:message.title}}}> {message.title}</Link>
    
                  </li>
                );
              })}
            </ul>
    
            <hr />
    
            {/*声明接受 */}
            <Route path="/about/right/message/details" component={ Details}/> 
         
          </div>
        );
      }
    }
    
    

    messageDetails:

    import React, { Component } from "react";
    
    import qs from "querystring";
    
    export default class Details extends Component {
      state = {
        messageDetail: [
          {
            id: "01",
            content: "你好中国"
          },
          {
            id: "02",
            content: "你好南京"
          },
          {
            id: "03",
            content: "你好杭州"
          }
        ]
      };
      render() {
        console.log(this.props);
        // 接收search
        const { id, title } = this.props.location.state;
        const result = this.state.messageDetail.find(value => {
          return value.id == id;
        });
    
        console.log(result);
        return (
          <li>
            <ul>
              <li>id:{id}</li>
              <li>title:{title}</li>
              <li> content:{result.content}</li>
            </ul>
          </li>
        );
      }
    }
    
    

    注:

    • 刷新丢失。

    • 路径无提示

    优点:优雅,可传对象。

    mark

    路由组件与一般组件

    mark

    最大区别就是:路由组件会受到路由器传递过来的props信息,核心的是上面三个。

    • 存放位置不同
    • 写法不同

    mark

    replace和push

    路由跳转的两种模式

    浏览器的存储区是以一个栈,每次push时都会压栈。

    mark

    replace则会替换每次的历史记录

    语法:replace={true}

      <Link  replace={true} to={ { pathname:'/about/right/message/details',state:{id:message.id,title:message.tit}}}> {message.title}</Link>
    

    默认是push模式

    编程式路由导航

    之前的路由跳转都是使用路由连接Link组件实现。

    但有些需求是路由是动态的,例如等待三秒后跳转路由。

    mark

    手动前进后退

    mark

    路由组件的懒加载

    路由的懒加载:将路由组件进行分包。可以提升首页的加载速度,提高用户的转化率。

    (1)引入

    import React, {lazy,Suspense} from 'react';
    import {BrowserRouter as Router, NavLink, Route} from "react-router-dom"
    

    (2)

    const One = lazy(() => import ("./pages/One"));
    const Two = lazy(() => import ("./pages/Two"));
    const Three = lazy(() => import ("./pages/Three"));
    

    (3)使用

    <Router>
        <NavLink to={"/"} exact>one</NavLink>
        <NavLink to={"/two"}>two</NavLink>
        <NavLink to={"/three"}>three</NavLink>
        <Suspense fallback={<p>加载中......</p>}>
            <Route path={"/"} component={One} exact></Route>
            <Route path={"/two"} component={Two}></Route>
            <Route path={"/three"} component={Three}></Route>
        </Suspense>
    </Router>
    

    深入理解React:懒加载(lazy)实现原理

    使用loadable 插件

    (1)下载loader

    react-loadable  :  npm i react-loadable
    
    antd  :  npm i antd
    

    (2)引入使用

    import React from 'react'
    import {Router, Route, Switch,Redirect} from 'react-router-dom'
    import { createBrowserHistory } from 'history'
    
    import {loadable} from '@/utils/loadable'; //懒加载模块
    import Login from '@/pages/login';//普通加载模块
    const Main = loadable({loader: () => import('@/pages/main')});   //引用
    const NotFound404 = loadable({loader: () => import('@/components/NotFound/NotFound')});  //引用
    
    const history = createBrowserHistory();
    
    class RouteMap extends React.Component {
      render () {
        return (
          <Router history={ history }>
            <Switch >
              <Route path="/" exact component={Login}/>
              <Route path="/login" component={Login}/>
              <Route path="/main" component={Main}/>
              <Route path="/404" component={NotFound404}/>
              <Redirect from="/*" to="/404"/>
            </Switch>
          </Router>
        )
      }
    }
    
    export default RouteMap
    
    //_this.props.history.push('/main')//跳转可后退
    //_this.props.history.replace('/main')//跳转不可后退
    // <Redirect  from="/*" to="/" /> //重定向
    // <Route path="*" component={NotFound404}/>//默认
    

    1.代码分割

    (1)为什么要进行代码分割?

    现在前端项目基本都采用打包技术,比如 Webpack,JS逻辑代码打包后会产生一个 bundle.js 文件,而随着我们引用的第三方库越来越多或业务逻辑代码越来越复杂,相应打包好的 bundle.js 文件体积就会越来越大,因为需要先请求加载资源之后,才会渲染页面,这就会严重影响到页面的首屏加载。

    而为了解决这样的问题,避免大体积的代码包,我们则可以通过技术手段对代码包进行分割,能够创建多个包并在运行时动态地加载。现在像 Webpack、 Browserify等打包器都支持代码分割技术。

    (2)什么时候应该考虑进行代码分割?

    这里举一个平时开发中可能会遇到的场景,比如某个体积相对比较大的第三方库或插件(比如JS版的PDF预览库)只在单页应用(SPA)的某一个不是首页的页面使用了,这种情况就可以考虑代码分割,增加首屏的加载速度。

    2.React的懒加载

    示例代码:

    import React, { Suspense } from 'react';
    
    const OtherComponent = React.lazy(() => import('./OtherComponent'));
    
    function MyComponent() {
     return (
       <div>
         <Suspense fallback={<div>Loading...</div>}>
           <OtherComponent />
         </Suspense>
       </div>
     );
    }
    

    如上代码中,通过 import()React.lazySuspense 共同一起实现了 React 的懒加载,也就是我们常说了运行时动态加载,即 OtherComponent 组件文件被拆分打包为一个新的包(bundle)文件,并且只会在 OtherComponent 组件渲染时,才会被下载到本地。

    那么上述中的代码拆分以及动态加载究竟是如何实现的呢?让我们来一起探究其原理是怎样的。

    import() 原理

    import() 函数是由TS39提出的一种动态加载模块的规范实现,其返回是一个 promise。在浏览器宿主环境中一个import()的参考实现如下:

    function import(url) {
     return new Promise((resolve, reject) => {
       const script = document.createElement("script");
       const tempGlobal = "__tempModuleLoadingVariable" + Math.random().toString(32).substring(2);
       script.type = "module";
       script.textContent = `import * as m from "${url}"; window.${tempGlobal} = m;`;
    
       script.onload = () => {
         resolve(window[tempGlobal]);
         delete window[tempGlobal];
         script.remove();
       };
    
       script.onerror = () => {
         reject(new Error("Failed to load module script with URL " + url));
         delete window[tempGlobal];
         script.remove();
       };
    
       document.documentElement.appendChild(script);
     });
    }
    

    当 Webpack 解析到该import()语法时,会自动进行代码分割。

    React.lazy 原理

    以下 React 源码基于 16.8.0 版本

    React.lazy 的源码实现如下:

    export function lazy<T, R>(ctor: () => Thenable<T, R>): LazyComponent<T> {
     let lazyType = {
       $$typeof: REACT_LAZY_TYPE,
       _ctor: ctor,
       // React uses these fields to store the result.
       _status: -1,
       _result: null,
     };
    
     return lazyType;
    }
    

    可以看到其返回了一个 LazyComponent 对象。

    而对于 LazyComponent 对象的解析:

    ...
    case LazyComponent: {
     const elementType = workInProgress.elementType;
     return mountLazyComponent(
       current,
       workInProgress,
       elementType,
       updateExpirationTime,
       renderExpirationTime,
     );
    }
    ...
    function mountLazyComponent(
     _current,
     workInProgress,
     elementType,
     updateExpirationTime,
     renderExpirationTime,
    ) { 
     ...
     let Component = readLazyComponentType(elementType);
     ...
    }
    // Pending = 0, Resolved = 1, Rejected = 2
    export function readLazyComponentType<T>(lazyComponent: LazyComponent<T>): T {
     const status = lazyComponent._status;
     const result = lazyComponent._result;
     switch (status) {
       case Resolved: {
         const Component: T = result;
         return Component;
       }
       case Rejected: {
         const error: mixed = result;
         throw error;
       }
       case Pending: {
         const thenable: Thenable<T, mixed> = result;
         throw thenable;
       }
       default: { // lazyComponent 首次被渲染
         lazyComponent._status = Pending;
         const ctor = lazyComponent._ctor;
         const thenable = ctor();
         thenable.then(
           moduleObject => {
             if (lazyComponent._status === Pending) {
               const defaultExport = moduleObject.default;
               lazyComponent._status = Resolved;
               lazyComponent._result = defaultExport;
             }
           },
           error => {
             if (lazyComponent._status === Pending) {
               lazyComponent._status = Rejected;
               lazyComponent._result = error;
             }
           },
         );
         // Handle synchronous thenables.
         switch (lazyComponent._status) {
           case Resolved:
             return lazyComponent._result;
           case Rejected:
             throw lazyComponent._result;
         }
         lazyComponent._result = thenable;
         throw thenable;
       }
     }
    }
    

    注:如果 readLazyComponentType 函数多次处理同一个 lazyComponent,则可能进入Pending、Rejected等 case 中。

    从上述代码中可以看出,对于最初 React.lazy() 所返回的 LazyComponent 对象,其 _status 默认是 -1,所以首次渲染时,会进入 readLazyComponentType 函数中的 default 的逻辑,这里才会真正异步执行 import(url)操作,由于并未等待,随后会检查模块是否 Resolved,如果已经Resolved了(已经加载完毕)则直接返回moduleObject.default(动态加载的模块的默认导出),否则将通过 throw 将 thenable 抛出到上层。

    为什么要 throw 它?这就要涉及到 Suspense 的工作原理,我们接着往下分析。

    Suspense 原理

    由于 React 捕获异常并处理的代码逻辑比较多,这里就不贴源码,感兴趣可以去看 throwException 中的逻辑,其中就包含了如何处理捕获的异常。简单描述一下处理过程,React 捕获到异常之后,会判断异常是不是一个 thenable,如果是则会找到 SuspenseComponent ,如果 thenable 处于 pending 状态,则会将其 children 都渲染成 fallback 的值,一旦 thenable 被 resolve 则 SuspenseComponent 的子组件会重新渲染一次。

    为了便于理解,我们也可以用 componentDidCatch 实现一个自己的 Suspense 组件,如下:

    class Suspense extends React.Component {
     state = {
       promise: null
     }
    
     componentDidCatch(err) {
       // 判断 err 是否是 thenable
       if (err !== null && typeof err === 'object' && typeof err.then === 'function') {
         this.setState({ promise: err }, () => {
           err.then(() => {
             this.setState({
               promise: null
             })
           })
         })
       }
     }
    
     render() {
       const { fallback, children } = this.props
       const { promise } = this.state
       return <>{ promise ? fallback : children }</>
     }
    }
    

    小结

    至此,我们分析完了 React 的懒加载原理。简单来说,React利用 React.lazyimport()实现了渲染时的动态加载 ,并利用Suspense来处理异步加载资源时页面应该如何显示的问题。

    生活是一首长长的歌!
  • 相关阅读:
    vscode添加python文件头模板
    解决Win平台VSCode中Python在控制台输出中文乱码的问题
    Windows系统解决VSCode终端无法输入问题
    python中pip安装包出现Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None))…………或无法pip install packname安装依赖包
    GET和POST的本质区别
    文件名排序
    乱码加密解密
    jQuery.validator 自定义验证消息
    Oracle查询某个表被那些存储过程引用
    note4
  • 原文地址:https://www.cnblogs.com/wind-zhou/p/14806347.html
Copyright © 2011-2022 走看看