【React】部分

57 阅读6分钟

*高阶组件(HOC)

1.定义:高阶组件是参数为组件,返回值为新组件的函数
2.都用过哪些高阶组件:connect,withRoute

*setState是同步还是异步

setState 有同步也有异步
异步:react原生事件里的setState,写在生命周期里的setState
同步:原生js事件,setTimeoutsetInterval,ajax
为什么是异步:如果是同步,比如我连续调用5次,页面就会刷新5次,浪费性能,所以把它做成异步的,对同一个值进行多次setState,setState的批量更新策略会对其进行覆盖 取最后一次的执行结果,如果是同时setState多个不同的值,在更新时会对其进行合并批量更新

*memo:16.8 引入

*展示组件:公共组件 不包含 redux,dva 等具体状态,大部分参数是父组件传入

容器组件:父组件 包含 redux,dva 等状态,传递数据给展示组件

*Hook 使用

//useState
export default () => {
    //异步
    const [x1,setX1] = useState(1)
    const [x2,setX2] = useState(() => {
        //ajax
        if(true){
            return 3
        }else{
            return 2
        }
    })

const onClick = opt => {
    //异步(等一小会)
    setX1(x1 + 1)
    //prevState 上一次的值
    setX1(prevState => {
        console.log(prevState,'prevState');
        //return 出去的值就是x1的值
        return prevState
    })
    
    console.log(x1,'x1');
}

return (
    <div>
        <h1>{x1}</h1>
        <Button onClick={onClick}>改变x1</Button>
    </div>
 )
};
    
//useRef,createRef 区别
//1.createRef 只要组件重新渲染 createRef 就会重新执行
export default () => {
    const [x1,setX1] = useState(() => {
        return 1
    })
    //特性:useRef 页面渲染的时候只执行一次
    //特性:只有current读写
    //返回值:{current: undefined} 内存地址 abc
    //作用1.获取DOM
    //作用2.储存上一次的值
    const ref = useRef()
    const ref2 = createRef()
    
    const onClick = opt => {
        //ref.current === 1
        ref.current = x1
        ref2.current = x1
        //异步
        setX1(x1 + 1)
    }
    
    return (
        <div>
            <h1>{x1}</h1>
            <h1 ref={ref}>小花</h1>
            <h1 ref={ref2}>小蓝</h1>
            <Button onClick={onClick}>改变x1</Button>
        </div>
    )
 }
  

/*

用途:父组件刷新 子组件不刷新

返回一个新函数 如果依赖是空 新函数的指针永远不变

依赖是空 useCallback 永远只执行一次

const fn = useCallback(() => {
    //如果依赖变了 重新返回指针变了的新函数
    const fn = useCallback(() => {
        
    },[x])

*/

export default function UseCallback() {
    const [x,setX] = useState(0)
    
    //console.log('我是父组件,我执行了');
    
    //fn保存的123指针 -> () => console.log(1)
    //第一次渲染 fn 123
    //第二次 直接把123指针 给 fn
    //第三次 直接把123指针 给 fn
    const fn = useCallback(() => {
        //console.log(1)
    },[])
    
    return (
        <>
            <h1 onClick={() => setX(x + 1)}>x:{x}</h1>
            <QusecallBack 
            fn={fn} //123
            />
       </>
    )
}

/*

 特性:
 1.有一个返回值 回调函数里return 的值
 2.useMemo 立刻执行的
 
 const fn = useMemo(() => {
    return 123
    return () => {
    }
 },[])

*/

export default connect(({loading}) => {
    return {
        loading: !!loading.effects['upload/fetch']
    }
})(useCallback)
function UseCallback (props){
    const {dispatch,loading} = props
    const [forms] = Form.useForm()
    const [fileList,setFileList] = useState([])
    const [x,setX] = useState(20000)
    const [y,setY] = useState(20000)
    
    //第一次刷新 x === 20000
    //第二次 x === 20001
    const x1 = useMemo(() => {
        console.log('我执行了');
        let sum = 0
        for(let i=0; i<x; i++){
            sum += i
        }
        return sum
    },[x])
    
    return (
        <div style = {{background:'#000'}}>
            <h1>x:{x1}</h1>
            <h1>y:{y}</h1>
            <h1 onClick={()=>setX(x+1)}>x:{x}</h1>
            <h1 onClick={()=>setY(y+1)}>y:{y}</h1>
        </div>
    )
}

*Fiber

React Fiber是react执行渲染时的一种新的调度策略 javaScript是单线程的 一旦组件开始更新,主线程就一直被React控制 这个时候如果再次执行交互操作 就会卡顿 页面首次渲染会创建一颗结构,一模一样的Fiber节点数 Fiber在update的时候,会从原来的Fiber clone出一个新的Fiber 俩个Fiber diff出的变化 在更新结束后会取代之前的,Fiber节点树 渲染过程采用切片的方式 每执行一会儿 就歇一会儿 如果有优先级更高的任务 就会先去执行,降低页面发生卡顿的可能性,Fiber分片优先级分同步 异步 NoWork sync async,Fiber 更新任务分成俩个阶段 调节阶段 和 交付阶段 调节阶段 找出要做的更新工作可以被打断 例如 setState,useState,交付阶段需要提交所有更新并渲染 被设置为不能打断(然后说一下协调的三种diff算法),fiber 是个链表,有child和sibing属性 指向一个子节点和相邻的兄弟节点 从而构成 fiber tree 

*JSX

是一个包含type,props,children的对象

*class生命周期

(react 16.4 之前)
三个阶段:加载阶段 更新阶段 卸载阶段
    
    加载阶段:
        constructor
        render
        componentDidMount
    
    更新阶段:
        componentWillReceiveProps(props)
        shouldComponentUpdate(nextProps,nextState):nextProps && this.props(旧的)
        render
        componentDidUpdate
        
    卸载阶段:
        componentWillUnmount
        
  (react 16.4 之后)
  三个阶段:加载阶段 更新阶段 卸载阶段
  
      加载阶段:
          constructor
          //getDerivedStateFromProps:
              //1.里面没有 this
              //2.return 的值 是改变 state,如果你不想改变state 就返回return null
          getDerivedStateFromProps(nextProps,state)
          render
          componentDidMount
     
      更新阶段:
          getDerivedStateFromProps(nextProps,state)
          shouldComponentUpdate(nextProps,nextState)
          render
          getSnapshotBeforeUpdate(nextProps,prevState)
          componentDidUpdate
          
      卸载阶段:
          componentWillUnmount
          

*PureComponent:优化子组件渲染,自动判断基础类型数据,引用类型数据根据指针是否变化判断子组件是否渲染

*redux 工作流程:

view -> action -> state -> 重新渲染视图
redux react-redux redux-actions redux-persist redux-promise redux-thunk

*虚拟DOM

虚拟DOM是一个对象,包含type表示节点类型,props属性,props下包含children属性,子节点又包含,type属性,props属性,children属性,js通过使用document.createElement,document.createTextNode,递归循环这个对象,创建DOM树,然后用这个DOM树和真实DOM进行比较,这颗DOM树叫做虚拟DOM,react diff算法有三种:1.最外层节点不同,重新渲染全部节点,最外层节点相同则不重新渲染全部节点,2.相同节点的属性不同,只渲染不同的属性,不重新渲染节点 3.key相同不重新渲染节点,key不同重新渲染该节点

*react18:主要更新的是Concurrent并发(高优先级[不能打断],低优先级[可以打断])

1.startTransitionstartTransition(()=>{ }):不用isPending直接使用这个方法
2.const [isPending,startTransition] = useTransition:startTransition(() => {})
3.useDeferredValue(值):你不能改父组件 父组件传了一个值给子组件 在子组件里把这个值变成低优先级
4.useId():生成一个id
5.useInsertionEffect(() => {},[])//DOM变更前同步触发 主要用来加载css in js
6.ReactDOM.createRoot,root.render
7.<Suspense fallback = {<h1>loading...</h1>}>

*不使用 antd 封装 Modal 组件,使用 ReactDOM.createPortal 把 Modal 插入到 body 下面和 root 同级 (为什么要和root同级,如果不同级放在 root 内,在页面里某个 div 如果有 overflow:hidden,Modal 可能无法做全凭遮罩)

 <Modal 
  open={open}//bool
  title={title}//string
  close={close}//bool
  footer={footer}//按钮扩展
  onOk
  onCancel
  onClose //完全关闭
  chilren
  className
  width
  height
  遮罩
  style
  确定文字
  取消文字
  loading
 >
 </Modal>
 

*Context 旧的使用方式

<ThemeContext.Consumer>
    {
        value => {
            //value 父组件注入的值
        }
    }
<ThemeContext.Consumer>

*多页面应用 单页面应用

1.单页面应用(SPA)

(1)只有一个html文件,通过切换路由展示不同页面
(2)页面局部刷新
(3)不利于SEO(SEO:搜索引擎的优化,让我们的网站在搜索的时候靠前)
(4)不需要重复加载 css js ,所以页面切换后渲染快
(5)可以使用hash 也可以使用history模式(history模式上线后,刷新浏览器后页面会找不到,所以需要配置nginx)

2.多页面应用

(1)多个html页面
(2)切换页面 整个页面全部重新加载 用户体验差
(3)SEO实现容易

*react 实现 keep-alive 缓存:react-activation

*react 16.8 之前事件代理 事件委托 注册在document.onClick

react 16.8 root