美文网首页面试
React类组件和函数组件区别对比使用

React类组件和函数组件区别对比使用

作者: 踩坑怪At芬达 | 来源:发表于2020-01-06 15:36 被阅读0次

如果觉得还有点用,请您给我一个赞!您的赞是我坚持下去的动力

环境:react 16.12.0

这里将会用类和函数组件2种方法实现同一目标来对比他们的区别

目录

  • 子组件向父组件通信的方法(如何调用父组件方法)
  • 父组件向子组件通信的方法(如何调用子组件方法)
  • setState对象成员合并问题
  • state变化

子组件向父组件通信,调用父组件方法

案例:
我们实现一个子组件Input,带有一个输入框和一个提交按钮
再实现一个父组件Form,希望当Input组件内用户输入完毕点提交后,父组件能获得到通知并拿到Input的值

  • 函数式组件实现方式
    函数式子组件 Input.js
//写一个Input组件,作为子组件用
function Input(props){
  //用于存放输入的值
  const [state, setState] = useState({inputValue:''});

  function onClick(){
    //这里就是父组件传递给子组件的方法,子组件可以通过props直接调用
    props.onSubmit(state.inputValue);
  }

  function onInput(v){
    setState({inputValue:v.target.value});
  }

  return (
    <div>
      <input value={state.inputValue} onChange={onInput}  type="text" ></input>
      <button onClick={onClick}>提交</button>
    </div>
  );
}

export default Input;

函数式父组件 Form.js

import React from 'react';
import Input from './Input.js';

function Form(props){
  //提供给子组件使用
  function onSubmit(value){
    console.log(`子组件提交啦,用户输入的是:${value}`)
  }

  return (
    <div>
      <Input onSubmit={onSubmit} ></Input>
    </div>
  );
}
  • 类式组件实现方式
    类式子组件 Input.js
class Input_Class extends React.Component{

  constructor(props){
    super(props);
    this.state = {
      inputValue:''
    }
  }

  onClick=()=>{
    this.props.onSubmit(this.state.inputValue);
  }

  onInput=(v)=>{
    this.setState({inputValue:v.target.value});
  }

  render(){
    return (
      <div>
        <input value={this.state.inputValue} onChange={this.onInput} type="text" ></input>
        <button onClick={this.onClick}>提交</button>
      </div>
    );
  }
}
export default Input_Class;

类式父组件 Form.js


class Form_Class extends React.Component{
  constructor(props){
    super(props);
    this.state = {}
  }

  onSubmit =(value)=>{
    console.log(`子组件提交啦,用户输入的是:${value}`)
  }

  render(){
    return (
      <div>
          <Input onSubmit={this.onSubmit} ></Input>
      </div>
    );
  }

}

父组件向子组件通信,调用子组件内的方法

案例:
我们实现一个Input组件作为子组件
实现一个Form组件作为父组件
父组件内通过按钮点击后需要调用子组件Input内的clear()方法来清空输入框

实现方法如下:

  • 函数式组件实现方式
    子组件 Input.js
import React, { useState,useImperativeHandle,forwardRef }  from 'react';

//写一个Input组件,作为子组件用
function Input(props,ref){
  //用于存放输入的值
  const [state, setState] = useState({inputValue:''});

  //用于清除输入框里的内容
  function clear(){
    setState({inputValue:''});
  }

  //这里就是用来暴露给ref.current下面的东西
  useImperativeHandle(ref, () => ({
    //我们暴露给ref.current.clear()这么一个方法,用来调用内部的clear()
    clear: () => {
      clear();//这里调用内部的clear,当然你可以直接将clear的实现体写在这里
    }
  }));

  return (
    <div>
      <input value={state.inputValue} onChange={onInput}  type="text" ></input>
    </div>
  );
}
Input= forwardRef(Input);
export default Input;

父组件 Form.js

import React, { useState,useRef } from 'react';
import Input from './Input.js';

function Form(props){
  const refInput=  useRef();//生成一个ref一会儿用来绑定Input子组件
  function onClick(){
    //通过ref.current可以获取子组件内暴露给父组件的所有对象
    refInput.current.clear();
  }

  return (
    <div>
      <Input ref={refInput} ></Input>
      <button onClick={onClick}>清除输入框的内容</button>
    </div>
  );
}
  • 类式组件实现方式
    子组件 Input.js -- 如果子组件是类式组件,则不需要做任何特殊处理
class Input_Class extends React.Component{

  constructor(props){
    super(props);
    this.state = {
      inputValue:''
    }
  }

  onClick=()=>{
    this.props.onSubmit(this.state.inputValue);
  }

  clear=()=>{
    this.setState({inputValue:''});
  }
  onInput=(v)=>{
    this.setState({inputValue:v.target.value});
  }
  render(){
    return (
      <div>
        <input value={this.state.inputValue} onChange={this.onInput}  style={styleInput} type="text" ></input>
        <button onClick={this.onClick} style={styleBtn}>提交</button>
      </div>
    );
  }
}

父组件 Form.js

需要注意在antd2-3下,对于被Form.create()的组件,需要通过<Component wrappedComponentRef={ref=>this.ref=ref} /> 来获取到真实ref


class Sortable_Class extends React.Component{
  constructor(props){
    super(props);
    this.state = {}
    this.refInput = React.createRef();
  }

  btnSubmit=(value)=>{
    console.log(`input value:${value}`);
  }
  btnClearInput=()=>{
    this.refInput.current.clear();
  }

  render(){
    return (
      <div>
          <Input ref={this.refInput} onSubmit={this.btnSubmit} ></Input>
          <button onClick={this.btnClearInput}>清空输入框</button>
      </div>
    );
  }

}

setState

在函数式组件中,setState的时候不会合并对象成员,我们需要手动使用{...param,...newParam}等方式进行合并

函数式组件


function Counter() {
  const [param,setParam] = useState({a:1,b:2})

  useEffect(() => {
    setParam({b:3});// 解决方案: setParam( {...param,...{b:3}} )
  },[]); 
  
  return (
    <>
      param:{JSON.stringify(param)}
    </>
  );
}

渲染输出param:{b:3}

类式组件

class CounterClass extends React.Component{
  constructor(props){
    super(props);
    this.state = {
      a:1,
      b:2,
    }
  }
    
  componentDidMount() {
    this.setState({b:3});
  }

  render(){
    return (
      <>
        param:{JSON.stringify(this.state)}
      </>
    );
  }
}

渲染输出param:{a:1,b:3}

但是如果遇到多层结构对象的时候,由于setState只做浅拷贝所以会出现问题
 this.state = {
      objList: {
        objA: {
          list: [],
          selected: 0,
        },
        objB: {
          list: [],
          selected: 1,
        },
      }
    }

var obj = {
      objList:{
        objB:{
          list:[5,2],
          selected:11
        }
      }
    };
this.setState(obj);

这里setState后的结果是 {"objList":{"objB":{"list":[5,2],"selected":11}}} ,objA没了

解决方案是在多层的时候将外层的对象进行展开合并

 var obj = {
      objList:{
        ...this.state.objList, //展开父级
        objB:{
          list:[5,2],
          selected:11
        }
      }
    };

    this.setState(obj);

state变化

当我们点击一个按钮时触发一个延时alert,时间到了打印count的值

函数式组件

function Counter() {
  const [count,setCount] = useState(0);
  //const countRef = useRef();
  //useEffect(()=>{countRef.current=count});

  function handleClick(count) {
    setTimeout(() => {
      alert('You clicked: ' + count);
      //alert('You clicked:' + countRef.current);
    }, 3000);
  }

  return (
      <div>
        <p>{count}</p>
        <button onClick={() => setCount(count + 1)}>
          Click me
        </button>
        <button onClick={handleClick}>
          Click Show Counter
        </button>
      </div>
  );
}

加入点击Click Show Counter后点击3下Click me,则输出结果为: 0
这是由于handleClick调用时,count以当时的值存在闭包内,所以延时后打印的值任是0,解决方法为使用 useRef,代码片段中注释的部分打开

类式组件

export class CounterClass extends React.Component{
  constructor(props){
    super(props);
    this.state = {count:0}
  }

  handleClick=()=>{
    setTimeout(() => {
      alert('You clicked: ' + this.state.count);
    }, 3000);
  }

  render(){
    return (
      <>
        <p>{this.state.count}</p>
        <button onClick={() => this.setState({count:this.state.count+1})}>
          Click +1
        </button>
        <button onClick={this.handleClick}>
          Click Show Counter
        </button>
      </>
    );
  }

加入点击Click Show Counter后点击3下Click me,则输出结果为: 3

如果觉得还有点用,请您给我一个赞!您的赞是我坚持下去的动力

相关文章

  • 最新面试集合

    react 1,react类组件和函数组件区别 函数组件:function Welcome (props) {re...

  • React - 类组件创建

    React创建组件有两种方式 函数式组件 类组件函数式组件已经学过,现在看下类组件怎么写。 函数式组件和类组件区别...

  • React_hooks

    React_hooks React16.8新增的特性,主要针对函数组件 一、函数组件和类组件的区别 函数组件的运行...

  • React学习笔记_02

    React 组件和状态 react 组件 1,组件的两种创建方式1,函数组件2,类组件 1,函数组件:使用 JS ...

  • React基础

    React包含react元素和react组件 react元素 react组件 react组件分为函数组件和类组件 ...

  • React组件介绍

    组件介绍 React中组件主要可分为函数组件和类组件,两者区别是函数组件没有state和生命周期,故函数组件也称为...

  • React Hook

    简介 :原本函数组件和类组件同为react组件,但是由于函数组件为无状态组件,react hook 的引入,让函数...

  • React类组件和函数组件区别对比使用

    如果觉得还有点用,请您给我一个赞!您的赞是我坚持下去的动力 环境:react 16.12.0 这里将会用类和函数组...

  • react-函数组件

    react的组件有两种形式:函数组件和类组件。本文主要介绍下函数组件。 useState 代码片段 使用描述 1....

  • 十道前端面试题第【07】篇

    1、字节跳动三面之React面试 什么是虚拟DOM? 类组件和函数组件之间有什么区别? React中的refs作用...

网友评论

    本文标题:React类组件和函数组件区别对比使用

    本文链接:https://www.haomeiwen.com/subject/qlskactx.html