React组件基础

React事件机制

在react中,如果你写<div onClick={()=>{}}></div>,react不是将click事件绑定到了真实DOM上,而是使用了document监听了所有的事件,采用事件代理的方式。react是将事件中的内容处理成函数,当事件冒泡到document后直接调用函数执行。这样做的好处就是:

  1. 不用给每个DOM都绑定事件,减少内存的消耗。

  2. 在组件销毁时统一移除事件。

react中,冒泡到document上的事件不是浏览器的原生事件,而是react自己实现的合成事件。

//原始DOM
<div onclick="fn()"></div>
//react合成事件
<div onClick={fn}></div>

合成事件的优点:

  1. 磨平了浏览器之间的兼容性问题。

  2. 因为这个是react跨浏览器包装的,所以赋予了跨浏览器开发能力。

  3. 减少了内存的消耗。

React高阶组件

react高阶组件就是一个函数,它接收一个组件作为参数,并且返回一个组件。

优点:

  1. 代码复用

  2. 渲染劫持,鉴权

  3. state更改

  4. props更改

示例:

  1. 鉴权

import React from 'react'

export default function AuthComponent(Component) {
  const Test = (props) => {
    const { login } = props;
    if(login){
      return <Component {...props}/>
    }else{
      return <div>没有登录</div>
    }
  }
  return Test;
}
import React from 'react'
import AuthComponent from '../AuthComponent'

const Login = function Login() {
  return (
    <div>Login</div>
  )
}

export default AuthComponent(Login);
import Login from "./components/login";
function App() {
  return (
    <div>
      <Login login={true} />
    </div>
  );
}

export default App;
  1. 页面复用

//App.js
import {NewList, AttentionList} from "./components/list";
function App() {
  return (
    <div>
      <NewList />
      <AttentionList />
    </div>
  );
}

export default App;
//list.js
import React from 'react'
import withFetching  from '../WrappedComponent'

const List = (props) => {
  return (
    <div>{props.data}</div>
  )
}

export const NewList = withFetching(()=>'NewList')(List);
export const AttentionList = withFetching(()=>'AttentionList')(List);
//WrappedComponent.js
import React, { useEffect, useState } from 'react'

const withFetching = fetching => WrappedComponent => {
  const Fetch = (props) => {
    const [data, setData] = useState('');
    useEffect(()=>{
      //这里可以换成请求axios接口
      setData(fetching());
    },[]);
    return <WrappedComponent data={data} {...props} />
  }
  return Fetch;
}

export default withFetching;

哪些方法会触发React重新渲染,重新渲染render会做什么?

哪些方法会触发React重新渲染:

  1. 父组件的重新渲染。

  2. this.setState改变组件的值的时候,注意点是如果this.setState传入的是null则不会重新渲染render。

  3. 使用useState hooks更新值的时候。重新渲染render会做什么:

  • 会对新旧虚拟DOM进行比较,也就是diff算法。

  • 对新旧虚拟DOM树进行深度优先的遍历。

React状态组件和无状态组件

React受控组件和非受控组件

受控组件:比如用户在使用表单来收集用户的输入时,inputtextearea都要绑定一个onChange事件,当用户输入的时候就调用setState来改变值,这就让渲染的值与input上的value属性相对,让整个状态可控。

受控组件的缺点,如果输入框多的话,就需要给每一个输入框都绑定一个onChange事件,会让代码显得十分臃肿。所以就出现了非受控组件。

非受控组件:非受控组件就是使用ref从DOM上获取值,不用每个输入框都绑定一个onChange事件。

React类组件和函数组件的相同点和不同点。

相同点:它们都是React中可复用的最小代码片段,所以他们的使用方式和显示效果都一样,你甚至可以把函数组件改写成类组件,把类组件改写成函数组件。

不同点:

  • 心智模型不同,类组件面向对象编程,主打的是生命周期和继承。而函数组件内核是函数式编程,主打immutable、没有副作用、引用透明。

  • 在以前的使用场景中,如果需要使用生命周期的话和继承的话就使用类组件,但是现在React Hook的推出,让生命周期的概念渐渐消失。

  • 性能优化上,类组件使用的shouldComponentUpdate来阻断渲染的更新,而函数组件使用React.memo来缓存渲染结果。

  • 上手程度上,我个人认为类组件较容易上手,但是现在React Hook推出,让函数式编程成了主流方案。

  • 函数组件比较轻量级,类组件的生命周期如果过多,就会显得很复杂,则不易优化。