react面试题(一)

JSX语法

  1. 使用 JSX 语法,可以更好的描述UI呈现的样子,可读性强;
  2. JSX是 React.creatElement() 的语法糖,JSX用babel编译以后就是 React.createElement() 方法的调用;
  3. 相对于 Vue template 来说,JSX不需要引入新概念,用法与 JS 相同;

react的特性

  1. 使用JSX语法,可以更好的描述UI呈现的样子,可读性强;没有引入新概念,使用JSX语法,相比之下,Vue就有很多模版语法;
  2. 可以跨平台,可以与其他库一起使用,例如react-native;
  3. 使用Virtual DOM (Vue也用)和 Diff算法差异化更新,减少操作DOM,加快更新速度,但是需要消耗额外的内存(因为新增V-DOM);
  4. 使用Fiber架构,将 Virtual DOM 原本的结构替换为 fiber 节点,将原本的递归遍历改为循环遍历,切分工作单元,为不同类型的任务添加优先级,且允许中止/复用/重启渲染任务,这就是更新后的react diff算法;

fiber / React fiber

  1. fiber(纤维),意在表示比线程(Thread)更小的工作单元;
  2. diff 算法进行比较时,采用 fiber 节点替换原有的 Virtual DOM 结构,能够使得渲染过程可中断、复用、重启;
  3. react15之前流程:setState => 先协调(reconciler)任务 => 生成WorkInProgress Tree =>给有修改的 V-DOM 节点打 diff 标记 => render 修改节点,渲染页面
  4. 改为fiber节点以后,协调器从stack reconciler 换成 React fiber,将同步渲染改成了异步渲染;
  5. 流程变化:setState => 先协调(reconciler)任务 => 生成WorkInProgress fiber Tree =>给有修改的 fiber 节点打 diff 标记 => 生成新的WorkInProgress fiber Tree => render 修改节点(替换WorkInProgress fiber Tree),渲染页面

class组件与函数组件区别

  1. 编写形式的不同
    类组件使用es6去编写;继承于React.Component;
    函数组件通过函数的形式去实现一个React组件;
  2. 状态管理:类组件使用this.state改变状态值;函数组件使用hook进行状态管理,每一个状态值都有自己的setstate;
  3. 生命周期:类组件有生命周期;函数组件是无状态组件没有生命周期,可以用useEffect来代替生命周期的作用;
  4. 值捕获特性(capture value 固化值)
    类组件可以拿到最新state;
class CaptureValue extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      num: 0
    }
  }
  handleClick(){
    setTimeout(() => {
      console.log(this.state.num);//打印1
    }, 3000)
    this.setState({ num: 1 });
  }
  render() {
    return <button onClick={()=>this.handleClick()} >我是类组件</button>
  }
}

类组件打印结果

函数式组件有值捕获特性,每一次render都会保存自己的props和state,每一次render都是一个独立的过程;state 和 effect都具有固化值特性,所以导致下方打印的num是上一次render后缓存的num值;但是useRef可以跳过Capture Value,保持唯一引用,拿到最终状态,所以可以通过useRef获取最新值;
第一次render => 缓存这一次的state和props => 点击button,调用handleClick,获取到第一次的num => setNum(1) => 触发render => 缓存这次render后的固化值state => …

export default function CaptureValueFunction() {
  const [num, setNum] = useState(0);
  const handleClick = () => {
    setTimeout(() => {
      console.log(num);//打印0
    }, 3000)
    setNum(1);
  }
  return <button onClick={handleClick}>我是函数组件</button>
}

函数组件打印结果

  1. 调用方式:类组件需要先实例化组件,再调用实例的render方法;函数组件是一个函数,直接调用传入props即可;
//类组件code部分
class myComp extends React.Component {
	render(){
		return <div>我是类组件</div>
	}
}
//React内部执行
const instance = new myComp(props); //创建了一个myComp的实例,将props传进去
const result = instance.render(); //<div>我是类组件</div>
//函数组件code部分
function myComp(){
	return <div>我是函数组件</div>
}
//React内部执行
const result = myComp(props);//<div>我是函数组件</div>

hook和生命周期之间有什么关联?

  1. constructor
    函数组件创建执行相当于constructor,函数组件不需要constructor,可以使用useState初始化state;
  2. static getDerivedStateFromProps相当于useState里面的更新函数
    使用setState更新state,可以达到getDerivedStateFromProps的目的;它是一个静态函数;
  3. shouldComponentUpdate相当于useMemo和React.memo
    可以使用React.memo包裹组件,它会浅比较props,缓存组件;也可以用useMemo缓存每一个节点;
  4. render
    函数组件的返回值就是render的返回值,render相当于函数组件体本身;
  5. componentDidMount相当于useEffect
    componentDidMount里面需要执行的内容可以放在useEffect里面执行,它会在render后执行;
  6. getSnapshotBeforeUpdate
    在render之后DOM更新之前执行,获取最新的DOM数据,返回的值作为componentDidUpdate的第三个参数;
  7. componentDidUpdate(prevProps, prevState, snapshot)
  8. componentWillUnMount相当于useEffect返回的清除函数cleanup
    componentWillUnMount中需要清除的副作用可以在useEffect中返回一个清除函数,在这个清除函数中执行,它会在卸载之前执行;
  9. componentDidUnMount
  10. componentDidCatchgetDerivedStateFromError(捕获错误)
    暂时没有对应的hook;任何生命周期或者子组件的渲染阶段发生错误就会执行componentDidCatch(error,info);componentDidCatch打印错误信息;getDerivedStateFromError渲染备用UI;
class CatchError extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };//用这个state区分降级UI
  }
  static getDerivedStateFromError(error) {
    // 更新 state 使下一次渲染能够显示降级后的 UI
    return { hasError: true };
  }
 
  componentDidCatch(error, errorInfo) {
    // 错误日志发给服务器
    logErrorToMyService(error, errorInfo);
  }

  render() {
  	if(this.state.hasError){
  	//降级UI
  		return <h1>Someing is wrong.</h1>
  	}
    return <button onClick={()=>this.handleClick()} >我是类组件</button>
  }
}

哪些操作会触发react页面重新渲染

setState无条件触发 || props改变 || 父组件重新渲染 || context变化(可以使用useMemo包裹provider中的value可以避免不必要的re-render) || hooks变化

详情见此链接

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值