React 高级指引的学习笔记

无障碍

对于无障碍部分,没有深入进去研究和分析,个人认知是所有的功能按钮,操作都需要尽量贴合所有用户,对具有某些欠缺的用户也能有足够友好的浏览体验,比如所有的鼠标操作,都能够具备键盘控制等等,后续如果深入研究,再补充。

代码分割

在研究代码分割钱,首先需要明白什么是打包,作为一个初学者,使用过的框架只有webpack,对于React来说,有一个create-react-app能够很方便的完成一个简单的项目搭建,而项目搭建完成后,对于比较简单的单页面应用或者没有额外需求的项目来说,不需要进行优化,如果需要进一步进行配置,可以通过下列代码进行暴露配置:

npm run eject  或者  yarn eject

使用何种方法看各自的配置,在暴露后的文件中进行相应的配置即可,具体实现,等后面如果有深入研究再写。而react中代码分割主要讲的还是通过 import 来优化打包。至于为什么不是require,我也不清楚,不过这篇文章require和import的区别中写的比较清晰,个人认为是兼容性以及es6规范的考虑。

常用的import引入模块方式有很多:

import Comp from './Component'  //引入自定义组件
import { Button } from 'antd'   // 引入模块
import * as d3 from 'd3'    // 引入模块内所有,以d3作为对象
import Img from '../../../assets/images/test.png'  //引入图形

通过 import 引入的内容,如果是用create-react-app创建的项目,则在 webpack 打包时会自动进行分割,若果不是,就自己去搜索一下怎么配,网站上推荐了代码分割网站。

后面才是我认为的这节的重点 —— React.lazy(懒加载)。前文已经提到了组件通过正常的 import 引入,而懒加载的实现主要是依赖于 React 的两个部分 Suspenselazy ,你可以通过如下两种方式来使用它:

/**
 * @desc 方法1
 */
import React, { Component, Suspense, lazy } from "react";

// ps:常量定义在import之后
const Comp = lazy(() => import("@/pages/Comp"));

class Test extends Component {
  render() {
    return (
      <>
        loading...
}> ); } } /** * @desc 方法2 */ import React, { Component } from "react"; // ps:常量定义在import之后 const Comp = React.lazy(() => import("@/pages/Comp")); class Test extends Component { render() { return ( <> loading...
}> ); } }
ps:在使用lazy后,必须跟上Suspense包裹在外层

同时,Suspense内不是只能有一个lazy对象,他可以是多个对象,就是说只要在最外层使用了该模块,同一组件下的所有lazy都能被渲染出来,这在定义路由的时候尤为有效:

/**
 * @desc 懒加载结合路由导航
 */
import React, { Component, Suspense } from "react";
import { Switch, Route, Redirect, withRouter } from "react-router-dom";
import routes from "@/routes";
// import Navigation from "@/components/Navigation";
import { filiterRoutes } from "@/util";
import { message } from "antd";

@withRouter
class RouteOption extends Component {

  judgeRoute = (route, path) => {
    let bool = false;
    route &&
      route.length > 0 &&
      route.map((v) => {
        if (v.href === path) {
          bool = true;
        }
        return v;
      });
    return bool;
  };
  renderRoute = (routeslist) => {
    return (
      
        {routeslist.map((item, index, arr) => {
          if (arr.length > index + 1)
            return (
               }
              >
            );
          else {
            return (
              
                 }
                >
                
              
            );
          }
        })}
      
    );
  };
 
  render() {
    return (
      loading...
}> {this.renderRoute(routes)} ); } } export default RouteOption;

这并不是说你只需要在最外层定义一个Suspense包裹所有就可以完事了,如果你这样做了。。。。

/*
* @desc 这可真是太聪明了,编程我不行,偷懒第一名
*/
import React, { Component, Suspense } from "react";

...
...

class App extends Component {

...
...

  render() {
    return (
      
); } } export default App;

这就是结果:
React 高级指引的学习笔记_第1张图片

Context

虽然我总是觉得简单的上下层级传递参数用props这样的就行,页面间传递还有路由传参,或者是用redux、mobx等仓库组件,context有点鸡肋,但是还是看了一下,谁知道以后会不会用上呢。

  • 总的来说:context就类似于在最外层父组件包裹了一个公共数据,存储在最外层,这样,只要是被包裹的内层都可以去请求这个数据,也能根据这个数据的更新来同步更新组件,这样的方式避免了当你想要给重孙组件传递一个值时,你需要中间传递props3次:即父->子->孙->重孙,而context免去了这样的麻烦,只要在包裹内,你可以直接在重孙获取数据。
  • 可惜鸡肋的是,重孙不能操作数据的更改,所有变更都在最上层解决,这样的好处是避免了许多非可控的副作用,不好的点是,应用的地方我真的找不到多少(至少我是这样,可能接触的太少了)。

首先要使用createContext创建一个context对象,可以是简单的字符串,也可以是一个对象,不过不能是一个undefined的值。

const PowerContext = React.createContext("admin");
const PowerContext = React.createContext({
  name: "测试",
  sex: "female",
  age: 20,
});

随后把需要用到这些值的组件用Provider包裹起来。

 
    
        
    

最后在需要使用该数据的子节点中使用Consumer进行获取

function Layout() {
  return (
    <>
      
      
    
  );
}

function Content1() {
  return (
    
      {(admin) => (
        
          {(info) => {
            return admin === "admin" ? (
              

姓名:{info.name}

性别:{info.sex}

年纪:{info.age}

) : (

你没有权限

); }}
)}
); }

如此就完成了一个流程,即创建 => 包裹 => 调用

错误边界

相当于组件的 try catch ,能够捕捉到组件的异常,然后展示设置好的备用UI界面,以防异常显示带来的损失。下面是一个简答的错误边界组件demo:

/**
 * @desc 错误边界demo
 * @name ErrorBoundary
 * @author WebTeacher
 * @date 2020/11/10
 */

import React, { Component } from "react";
import styles from "./styles.module.less";

class ErrorBoundary extends Component {
  constructor(props) {
    super(props);

    this.state = {
      hasError: false,
      error: "",
      errorInfo: "",
    };
  }

  // 这个方法和下面使用其中一个就可以,然后我就用了比较习惯的下面那种
  // 在官方文档里面是说明了渲染备用UI用这个,抛出异常用下面那个
  static getDerivedStateFromError(error) {
    // 更新 state 使下一次渲染能够显示降级后的 UI
    return { hasError: true };
  }

  // 获取异常并抛出
  componentDidCatch(error, errorInfo) {
    this.setState({
      error: error,
      errorInfo: errorInfo,
    });
  }
  render() {
    if (this.state.hasError) {
      return (
        

似乎什么地方出了问题!

;
{this.state.error && this.state.error.toString()}
{this.state.errorInfo.componentStack}
); } return this.props.children; } } export default ErrorBoundary;

主要是通过componentDidCatchstatic getDerivedStateFromError 来获取错误。

Refs 转发

未完待续。。。

你可能感兴趣的:(react.js,javascript,es6)