初识React函数组件和类组件

在React组件化开发中,把组件分为函数组件、类组件、Hooks组件,这里本文先认识函数组件和类组件。

函数组件

使用 JS 函数(普通,箭头)创建的组件,就是函数组件,函数组件也称“静态组件”。

定义函数组件

  • 函数名称首字母必需大写,React 据此来区分组件和 HTML 元素
  • 函数必须有返回值,表示该组件的 UI 结构,如果不渲染任何内容可返回null

先来看看函数组件长啥样,看下面代码:

// 普通函数
function Header() {
  return <div>头部组件</div>;
}
// 箭头函数
const Footer = () => {
  return <div>底部组件</div>;
};
// 不渲染内容
const Loading = () => {
  const loading = false;
  return loading ? <div>正在加载...</div> : null;
};

上面创建的函数Header、Footer、Loading就是一个个函数组件了。那要怎么使用呢?

使用函数组件

// 创建一个Child子组件
function Child(props){
  let { title  } = props
   return  <div className="child">
   <h2>{title}</h2>
  </div>
}
// 父组件使用
function App(){
  return <Child title='用户投票数量'></Child>
}

以上函数的名称(Child)就是组件名称,使用组件就是把组件名称当标签使用即可。

静态组件
那函数组件为什么又称“静态组件”呢?看下面这段代码:

function Child(props){
  let { title  } = props
  let name =  '小浩', num = 0
   return  <div className="child">
   <h2>{title}</h2>
   <ul>
    <li>姓名:{name}</li>
    <li>票数:{num}</li>
   </ul>
   <div className="footer">
    <button  onClick={() => {
      num ++
      console.log('num-----',num)
    }}>投票</button>
   </div>
  </div>
}

浏览器效果:
React函数组件
以上当我们点击投票时,改变num的值,可以看到num在控制台输出的变化,但页面却没有更新视图。
综合以上,也就是函数组件中的内容,不会根据组件内的某些操作进行更新试图,所以称它为静态组件。除非在父组件中,有数据更新,那么对应的子组件也会更新。

类组件

使用class语法创建的组件就是类组件,类组件也称“动态组件”。

定义类组件

  • 类名首字母必需大写
  • 必须继承React.ComponentPureComponent这个类
  • 必须给当前类设置一个render的方法,这个方法是放在其原型上的,在render方法中,返回需要渲染的视图,无渲染可返回null
import React from 'react';

class Child extends React.Component{
  render(){
    let { title  } = this.props
    return <div className="child">
      <h2>{title}</h2>
    </div>
  }
}
export default Child

上面代码是用class创建的类Child且基于extends继承React.Component,在Child类里设置了一个render的方法,然后返回需要渲染的视图,这样的组件就是类组件了。

动态组件
那类组件为什么又称“动态组件”呢?看下面这段代码:

class Child extends React.Component{
  name =  '小浩'
  num = 0
  render(){
    let { title  } = this.props
    return <div className="child">
      <h2>{title}</h2>
      <ul>
        <li>姓名:{this.name}</li>
        <li>票数:{this.num}</li>
      </ul>
      <div className="footer">
        <button  onClick={() => {
          this.setState({
            num:this.num ++
          })
          console.log('num-----',this.num)
        }}>投票</button>
      </div>
    </div>
  }
}

浏览器效果:
React函数组件
以上当我们点击投票时,改变num的值,可以看到num在控制台输出的变化,但页面也随着更新视图。
综合以上,也就是类组件中的内容,会根据组件内的某些操作改变状态,当状态改了,浏览器里视图也更新了,所以称这样的组件为动态组件。在上面用来改变num值的方法this.setStateReact.Component.prototype原型上提供的方法,后面会说到。

class类组件做了些什么
创建new Child()实例,类组件内部发生了什么?下面来看看这段代码:

class Child extends React.Component{
  name = '小浩'
  age = 30
  work = ()=>{
    console.log('程序员')
  }
  run(){
    console.log('跑步')
  }
  render(){
    let { title  } = this.props
    return <div className="child">
      <h2>{title}</h2>
    </div>
  }
}

//创建实例p
const p = new Child()
console.log(p)

上面添加的name、age、workChild的私有属性,而添加的run方法是Child.prototype上的方法。
由于Childextends实现的继承,所以有以下特点:
1、先是基于call继承,相当于执行了React.Component.call(this),把this指向了Child类的实例p

React类函数组件
也就是执行了这个Component函数。在执行了React.Component.call(this)后给创建的实例p设置了四个私有属性: props、context、refs、updater

2、再基于原型继承:Child.prototype.__proto__ == React.Component.prototype

这样实例可以沿着原型链访问:实例 -> Child.prototype -> React.Component.prototype -> Object.prototype,实例除了具备Child.prototype提供的方法之外,还具备React.Component.prototype原型上提供的方法: isReactComponent、setState、 forceupdate
React类函数组件

3、构造函数constructor
既然是类组件,那么在类组件里面就会存在一个构造函数constructor,这个函数可写可不写,只有需要接受传递进来的实参信息时,才需要设置constructor。如果写了constructor那么在函数里一定要写super()方法。

class Child extends React.Component{
  constructor(props){
    super(props)
  }
  render(){
    let { title  } = this.props
    return <div className="child">
      <h2>{title}</h2>
    </div>
  }
}

上面的super(props)就等价于React.Component.call(this),在执行了super(props)Child就增加了四个私有属性: props、context、refs、updater,它们当前的状态分别是 :

this.props=props 
this.context=undefined 
this.refs={} 
this.updater=(...}

使用类组件
创建类组件Child

import React from 'react';
class Child extends React.Component{
  render(){
    let { title  } = this.props
    return <div className="child">
      <h2>{title}</h2>
    </div>
  }
}
export default Child

父组件使用Child组件

function App(){
  return <div>
    <Child title='用户投票数量1'></Child>
    <Child title='用户投票数量2'></Child>
  </div>
}

上面使用了两次Child类组件,相当于创建了两个实例,如下:

new Child({
 title:'用户投票数量1'
})
new Child({
 title:'用户投票数量2'
})

由此可知,同一个组件多次调用,互相之间不会产生直接的影响,因为每次调用都是创建的一个单独的实例。


 上一篇
React类组件的生命周期 React类组件的生命周期
组件的生命周期 组件从先创建,然后挂载到页面中运行,最后组件不用时卸载的过程,这个过程就叫做组件的生命周期。而在这个过程中,React提供了在适当的时候会自动执行的不同的函数,我们称之为生命周期函数,也称钩子函数。组件的生命周期分为三个阶段
2022-04-08
下一篇 
React中的插槽 React中的插槽
在开发中,我们抽取了一个组件,但是为了让这个组件具备更强的通用性,我们不能将组件中的内容限制死了。我们应该让使用者决定这一块区域应该显示什么内容。那么应该怎么做呢?这就需要使用所谓的插槽了,那什么是插槽呢? 什么是插槽 简单来说,插槽(sl
2022-04-07
  目录