前端八股-react

react优点:组件化、虚拟DOM、JSX语法、单向数据流、兼容性好

#react18新特性

  • 服务器组件:将组件的渲染逻辑客户端移动到服务器端,以更好地利用服务器资源
  • 并发模式的改进:1、更好的错误处理(引入了新的错误边界机制);2、更可预测的渲染和更新行为(改进任务调度算法批处理机制);3、更好的可中断和恢复能力(Fiber协调引擎
  • 自动批量更新:1、调用堆栈:React跟踪组件函数的调用过程,将脏组件标记为dirty,延迟更新操作。2、优先级:React为状态更新分配优先级,按照优先级进行调度和执行。

#react生命周期

组件挂载时

挂载阶段组件被创建,然后组件实例插入到DOM中,该过程只发生一次

  • constructor() 组件构造函数
  • componentWillMount dom树开始挂载前
  • static getDerivedStateFromProps() 静态方法;接收两个参数:props接收的参数和state组件状态
  • render() 根据传参props、state状态开始渲染组件
  • componentDidMount() dom树挂载完成

组件更新时

  • static getDerivedStateFromProps()
  • shouldComponentUpdate() 比较props、state,来确定返回true/false;false组件更新停止;
  • render()
  • getSnapshotBeforeUpdate() 更新前
  • componentDidUpdate() 更新后

组件卸载时:componentWillUnmount() 将要卸载

错误处理

  • static getDerivedStateFromProps()
  • componentDidCatch() 抛出错误,接收两个参数:error、info
#React发起网络请求在哪个生命周期

我一般在componentDidMount

  • 异步请求,最好放在componentDidMount中去操作
  • 同步的状态改变,可以放在componentWillMount中
#React中可以在render访问refs吗

不可以render阶段DOM还没有生成,无法获取 DOM。需要在componentDidMount() dom数挂载完之后

#Fragment

概念:Fragment作为根标签包裹元素,Fragment不会有任何元素渲染;

#获取组件DOM

  • 1 ref <h2 ref="hello">Hello World</h2>

  • 2 createRef()

import React, { PureComponent, createRef } from 'react'
export class App extends PureComponent {
  constructor() {
    super()
    // 提前创建一个ref对象
    this.titleRef = createRef()
  }
  getDom() {
    console.log(this.titleRef.current) // <h2>Hello World</h2>
  }
  render() {
    return (
      <div>
        <h2 ref={this.titleRef}>Hello World</h2>
        <button onClick={() => this.getDom()}>获取DOM</button>
      </div>
    )
  }
}
export default App

#React事件代理/原理

  • 事件机制/委派:把所有的事件绑定到结构的最外层document使用统一的事件监听器
  • 自动绑定自动绑定this为当前组件
#react事件机制

核心:document处监听了所有的事件

click事件不是绑定到了div的真实DOM上,而是在document处监听了所有的事件,当事件发生并且事件冒泡到document处。这样减少了内存的消耗

#组件

#函数组件/类式组件区别

最大的区别:有无状态、生命周期、class

  • 函数组件-面向函数式编程
# 通过函数创建;无状态组件;场景:组件不需要管理state
  • 类式组件-面向对象编程
# 基于ES6语法class创建;通过extends React.component得到的组件;
# 补充:还有React.createClass({})创建

区别

  • 类组件有生命周期,函数组件没有
  • 类组件需要继承 Class,函数组件不需要
  • 类组件内部可以定义并维护 state, 函数组件为无状态组件
#高阶组件HOC/Render props/hooks区别
  • HOC
# 概念:高阶组件(HOC)是一个函数,传入一个组件返回一个新组件,并且是一个纯函数没有副作用
# 优点:代码复用、逻辑抽象
  • Render props
# 组件之间的代码共享props
  • hooks
# hooks作用:1 组件内部有了维护状态的能力;2 组件的逻辑复用能力;通常函数名字都是以use开头
#PureComponent纯组件

PureComponent:对props和state浅层比较,跳过不必要的更新,提高组件性能

补充:浅层比较原理:只做对象的每个key的引用比较不深层遍历比较

#react创建组件
  • ES6 class创建组件
class MyComponent extends React.Component {
    render() {
        return Hello World!;
    }
}
  • React.createClass创建组件
var MyComponent = React.createClass({
    render() {
        return Hello World!;
    }
});
  • 函数组件
function MyComponent() {
  return Hello World!;
}

#Redx&react-redux

#Redux--了解即可

Redux概念:js状态容器;构建一致化的应用,运行与不同环境;并且体积小,只有2KB

Redux优点

  1. 状态的集中管理
  2. 任意页面与组件之间的数据传递
  3. 状态管理的可预测
  4. 数据的本地化缓存提升性能

三大核心

  • 核心1:store存放数据仓库:整个应用的state被存储在一颗object tree中,并且这个object tree只存在于唯一一个store

image-20230601210510661

  • 核心2:State数据唯一改变state的方法就是触发action,action是一个用于描述已发生事件的普通对象

  • 核心3:使用纯函数来执行修改:接收先前的state和action,并且返回新的state;

// dispatch唯一改变state的方法,通过提交action改变;是同步操作
store.dispatch(action)
// reducer 它负责对action变化进行分发和处理, 最终将新的数据返回给 store
#react-redux--要熟练
# 概念:是Redux官方出的用于配合React的绑定库;更方便的读取react store的数据
# 两个核心成员:Provider、Connect
  • Provider

概念:Provider是一个组件,作用:使得整个app都能获取到store中的数据;需要包裹整个结构

  • Connect

作用:接收Provider提供的store来获取的state;

  • 使用
// index.js
root.render(
  <Provider store={store}>
    <App3 />
  </Provider>
);

// store.js
import { createSlice } from '@reduxjs/toolkit'
export const counterSlice = createSlice({
  name: 'counter',
  initialState: {
    num: 0
  },
  reducers: {
    add: state => {
      state.num += 1
    },
    decrement: state => {
      state.num -= 1
    },
    // action传值
    setNum: (state, action) => {
      state.num = action.payload
    }
  }
})
// 
export const { add, decrement, setNum } = counterSlice.actions
export default counterSlice.reducers

// 页面使用
import { useDispatch, useSelector } from 'react-redux';
const dispatch = useDispatch()//修改值
const num = useSelector(state => state.counter.num)//获取值
dispatch(add())//修改值

#React-Fiber

概念: React 16 中新的协调引擎,是协程。

  • 为什么出现:在 React 16以前,更新过程是同步的,js执行占用主线程,虚拟树计算阻塞了浏览器的渲染。React Fiber很好的解决这个问题;

  • 具体怎么做的:Fiber把耗时长任务拆分成很多小任务(执行时间短);功能有:1 不同任务分配优先极; 2 更新时能暂停、终止渲染任务

#组件通信

React组件间通信常见的几种情况:

  • 1 父子组件通信
  • 2 嵌套关系组件通信
  • 3 非嵌套关系的组件通信--事件总线eventbus、redux
#父子组件通信
  • 父传子
//子组件:props接收
<p>{props.name}</p>
//父组件:变量传递
<child name="react"></Child>
  • 子传父
//子组件:props.callback(msg)
//父组件:callback(msg){console.log(msg)}
#嵌套关系组件通信

createContext实现;

  • .Consumer包裹传递参数
const BatteryContext = createContext();
<BatteryContext.Consumer>
    {
    	//传递的数据data=..
	}
</BatteryContext.consumer>
  • .Provider接收孩子组件数据
<BatteryContext.Provider value={data}>
    <Child></Child>
</BatteryContext.Provider>
#非嵌套关系组件通信:

react-redux等进行全局状态管理

#React-Router路由

#路由原理

补充:路由模式:HashRouter、BrowserRouter

  • HashRouter:基于hash :通过监听hashchange事件,感知hash的变改变hash 可以直接通过windows.location.hash=xxx
  • BrowserRouter:基于H5 history:改变url可以通过history.pushState,会将URL压入堆栈,同时能够应用**history.go()/history.back()**等API
// 浏览器路由:history API控制路由跳转
<BrowserRouter basename=" /calendar">
    <Link to=" /today">
</BrowserRouter>

// hash路由;通过URL的hash属性来控制路由跳转
<HashRouter basename={string} getUserConfirmation={func}hashType={string}/>

补充:hash类型有:slash 路由就是#/;noslash 路由就是#;hashbang #!/

#实现路由切换

路由跳转:

  • 事件跳转:this.props.history.push('路由')
  • 标签跳转<Link to="Home">to Home</Link>类;似a标签的形式;

Link与a标签区别:

  • Link一般配合route使用,阻止了a标签默认事件,link区别在于只会匹配对应的route的更新a会整个页面更新

<Route>路由组件<Switch>是将路由组件分组Redirect重定向;

Route中的exact是精确匹配,防止前面有/匹配;

<Switch>
    <Route exact path={"/home"} component = { Home }></Route>
    <Route path={"/user"} component = { User }></Route>
    <Redirect to='/home/goods'/>
</Switch>
#获取URL的参数和历史对象
  • 获取get传参:调浏览器api,URLSearchParams
  • 获取动态路由传值:this.props.match.params
  • 获取query/state传值:this.props.location.state、this.props.location.query

补充获取历史对象:useHistory API、this. props.history

#hooks

hooks作用:1组件内部有了维护状态的能力;2组件的 逻辑复用能力

  • useState 让函数式组件拥有状态
const [count, setCount] = useState(0);//变量、更新变量的方法

useState原理:

  • useEffect 模拟生命周期componentDidMount(return前) shouldComponentUpdate(监听更新) componentWillUnmount(return里面)
useEffect(() => { 
    // 在此可以执行任何带副作用操作
    return () => { // 在组件卸载前执行---
        // 在此做一些收尾工作, 比如清除定时器/取消订阅等
    }
}, [stateValue]) // []空代码不监听,[变量]检测数据更新
  • useContext 共享状态钩子:一种组件间通信方式, 常用于爷孙组件传值
  • userRef 存储组件属性
import React, { useRef, useEffect } from "react"

function App () {
   //声明绑定的元素/组件
  const pRef = useRef(null)
  const testRef = useRef(null)
  
  useEffect(() => {
    //.current获取到的dom对象
    console.log(pRef.current)
    console.log(testRef.current)
  }, [])
  return (
    <div>
      //通过ref绑定元素/组件
      <Test ref={testRef} />
      <p ref={pRef}>this is p</p>
    </div>
  )
}
  • memo-性能优化,缓存组件
# 作用:缓存组件,解决父组件不传任何值,影响子组件刷新问题(原理:默认是全等对比,默认空props也是不全等的,因此刷新子组件);
# 仍存在问题:父传子自定义的静态方法,仍然会照成子组件的刷新(原理:静态方法是闭包,默认每次的都不一样);需配合useCallback解决
  • useCallback-性能优化,缓存组件
# usecallback缓存函数;,配合memo使用,解决memo中传自己方法导致子组件刷新问题;
  • useMemo-性能优化,缓存组件
# usememo缓存值,计算然后再返回值的函数,函数中需要return
#useState使用数组而不是对象

如果是对象,解构赋值时那个变量就写死了。如果是数组,就可以自定义设置变量名来解构

#usecallback/usememo区别

react性能优化hook;

  • 区别1: usecallback缓存函数,函数的调用不影响子组件更新;usememo缓存值(计算然后再返回值的函数,函数中需要return)
  • 区别2:usecallback参数:函数/依赖项数组; usememo参数:函数(缓存需要计算的值)/依赖项数组
#useEffect新建项目后会更新两次

dom渲染完执行,代替生命周期

  • 原因:兼容以前旧版本的React
  • 发生场景:只发生在 development mode 中、并且是strict mode;解决办法:禁用 strict mode
#useState中的State里的对象值更新会重新渲染吗
  • 不会,React中默认浅监听,当State值为对象时,栈中存的是对象的引用地址
#React Hook的使用限制有哪些
  • 1、不要在循环/条件判断/嵌套函数中调用Hook;
  • 2、在React的函数组件中调用Hook;

如何预防:

  • 1 、可以引入 ESLint的进行语法检测

为什么不能在逻辑判断里写hooks:

  • 1、无法保证 Hook 的调用顺序是稳定的,可能会导致状态更新的错误或不一致
#setState是同步还是异步

都有;

  • 异步:比如在React 生命周期事件和合成事件中
  • 同步:比如原生事件addEventListener, setTimeout、setInterval等事件中,就只能同步更新。
#hook底层结构
  • 底层结构基于链表,用于管理组件的状态实现状态的共享和复用

  • 每个组件实例都有对应的 Hooks 链表,用于存储其状态

  • Hooks 链表中的每个节点包含 Hook 值和与之相关的元信息

  • React 在组件渲染时根据 Hooks 的调用顺序来创建和管理 Hooks

#为什么React要用JSX

其实React 本身并不强制使用JSX。在没有JSX的时候,React 实现一个组件依赖于使用React.createElement函数;相比jsx更好用

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蹦卡啦撒卡玛卡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值