【react框架】一次性讲明白各个组件概念(类式组件与函数式组件、受控组件与非受控组件、简单组件与复杂组件、高阶组件)

类式组件与函数式组件

在react中书写的组件主要有两种方式,类式组件与函数式组件。其中概念我们都很清楚了,主要还是两者之间的差别不是很明白,今天来捋一捋。

类式组件

学习类式组件的前提知识点,建议看看我写的一个文章【es6入门】类的声明与继承,class与extends语法糖

<script type="text/babel">
	//1.创建类式组件
	class MyComponent extends React.Component { // 继承了react组件很多属性
		render(){
			//render是放在哪里的?—— MyComponent的原型对象上,供实例使用。
			//render中的this是谁?—— MyComponent的实例对象 也称为 MyComponent组件实例对象。
			console.log('render中的this:',this);
			return <h2>我是用类定义的组件(适用于【复杂组件】的定义)</h2>
		}
	}
	//2.渲染组件到页面
	ReactDOM.render(<MyComponent/>,document.getElementById('test'))
</script>

分两步去理解:

第一、每个类组件都是继承了React.Component的子类,这样子类也就拥有父类的很多属性或者说是api,例如钩子函数。

第二、执行了ReactDOM.render(<MyComponent/>...)之后,发生了什么?

  1. React解析组件标签,找到了MyComponent组件。
  2. 发现组件是使用类定义的,随后new出来该类的实例,并通过该实例调用到原型上的render方法。
  3. 将render函数返回的jsx转虚拟DOM再转为真实DOM,随后呈现在页面中。

函数式组件

<script type="text/babel">
	//1.创建函数式组件
	function MyComponent(){
		console.log(this); //此处的this是undefined,因为babel编译后开启了严格模式
		return <h2>我是用函数定义的组件(适用于【简单组件】的定义)</h2>
	}
	//2.渲染组件到页面
	ReactDOM.render(<MyComponent/>, document.getElementById('test'))
</script>

能看到相对于类组件来说,简单了很多,更【轻】了。

只需要看执行了ReactDOM.render(<MyComponent/>...)之后,发生了什么?

  1. React解析组件标签,找到了MyComponent组件。
  2. 发现组件是使用函数定义的,随后调用该函数,将函数返回的jsx转成虚拟DOM再转为真实DOM,随后呈现在页面中。

讨论出结论

相同点

一、可以看到类组件和函数组件最终都是要执行render函数,后面走的流程是一样的

不同点

一、书写方式不同

二、渲染时获取的状态不同

在类组件中我们获取props的某个值时,是这样获取的this.props.name,在函数组件中我们是这样获取的props.name,两者其实是大有区别的。

假设这俩个组件中都有一个方法,点击3s后打印出name的值。当开始点击后,父组件把name这个值修改了,类组件3后s打印出的值是最新的,而函数组件打印出的是旧的。

我的理解是,类组件通过this的方式去获取props,拿到的永远是最新的值。

而函数组件的props是从参数传递进来,每次函数组件render时,props都是当前状态下的数据,那么在点击时的函数组件拿到的name一直就是旧值并等待3s后打印,等父组件的name修改后,函数组件重新render,props的值更新,但是执行函数的还是上一个状态的函数组件,所以3s后打印的是旧值。

这并不是react函数组件的设计缺陷,而是本身设计如此。

那么类组件想模拟函数组件的这种特性咋办,可以利用闭包:

class MyComponent extends React.Component { 
	render(){
		const { name } = this.props
		const clickFn = () => {
			setTimeOut(()=>{
				console.log(name)
			}, 3000)
		}
		return <div onClick={clickFn}>点击</div>
	}
}

这样,当点击时,clickFn与name就形成了闭包关系,在内存中不会被销毁。


非受控组件与受控组件

我是这么理解的,非受控是数据发现变化后需要人为去触发组件事件,组件才去处理数据;而受控组件是只要数据有变化,组件就会自动处理数据;

事件久了可能不好记,其实只需要记住是数据控制组件自动更新的就是受控组件,反之。

写个受控组件的例子:

class Demo1 extends Component {
    constructor(props) {
        super(props);
        this.state = {
            value: props.value
        }
    }

    handleChange(e) {
        this.setState({
            value: e.target.value
        })
    }

    render() {
        return (
            <input value={this.state.value} onChange={e => this.handleChange(e)}/>
        )
    }
}

思考:

  • 一般受控组件优于非受控组件,因为非受控组件会可能使用refs(性能方面的考量)。
  • 要用受控还是非受控写法可能更多从代码的设计上去出发的。
  • 更多的时候,可能还是二者混用,所以平时写代码的时候多多思考下,是否要做到统一。

简单组件和复杂组件

只需要记住:拥有状态的组件就是复杂组件,就是state、prop等。

所以基本上都是复杂组件,这个概念没必要记。


高阶组件

简称HOC,是用来做组件公共逻辑抽离的一种解决方案,本身是一个函数,入参为一个组件,经过公共逻辑的附加或处理后返回一个新的组件。

个人之前尝试使用过,但对其使用上的概念还是很模糊的,比如它和专门写个公共组件的区别在哪里,有什么优势?

待我以后研究

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值