React中的函数式和类式组件

注:学习此篇内容一定要先把类的基本知识搞懂,可参考我另一篇文章: 三分钟让你搞懂Class类 - 掘金 (juejin.cn)

本文是对网站免费资源的知识总结,如侵联删。

函数式组件

类式组件的定义

废话不多说,直接上例子:

js 复制代码
<!-- 准备好一个"容器" -->
	<div id="test"></div>
	
	<!-- 引入react核心库 -->
	<script type="text/javascript" src="../js/react.development.js"></script>
	<!-- 引入react-dom,用于支持react操作DOM -->
	<script type="text/javascript" src="../js/react-dom.development.js"></script>
	<!-- 引入babel,用于将jsx转为js -->
	<script type="text/javascript" src="../js/babel.min.js"></script>
//1.创建类式组件
	<script type="text/babel">
		class MyComponent extends React.Component {
			render(){
				//render是放在哪里的?------ MyComponent的原型对象上,供实例使用。
				//render中的this是谁?------ MyComponent的实例对象 <=> MyComponent组件实例对象。
				console.log('render中的this:',this);
				return <h2>我是用类定义的组件(适用于【复杂组件】的定义)</h2>
			}
		}
		//2.渲染组件到页面
		ReactDOM.render(<MyComponent/>,document.getElementById('test'))
         </script>
  1. 如果你了解Class的相关知识,你就能知道render其实就是MyComponent实例原型对象上的一个方法而已,那么this自然就执行MyComponent组件实例对象
  2. 渲染组件时,React做了什么:
  • React解析组件标签,找到了MyComponent组件。
  • 发现组件是使用类定义的,随后new出来该类的实例,并通过该实例调用到原型上的render方法。
  • 将render返回的虚拟DOM转为真实DOM,随后呈现在页面中。

组件实例三大核心属性之一:state状态

如果你的组件是有状态(state)的,就是复杂组件,反之,就是简单组件

state就是数据,不管是Vue还是React,都是靠数据驱动视图,只不过底层使用了响应式原理和自动更新视图

因为函数式组件是没有this的,因为函数式组件中采用了严格模式,而严格模式下没有this,就别谈组件实例,更别谈组件实例的核心属性了

只有类式组件有,但是后来react增加了hooks,函数式组件也有了状态

state中的this问题(重要)

那么state在哪里呢?其实React已经给我们封装好了,我们在render中打印this会发现在组件的实例对象中有context、props、refs、state等初始值 如果我们需要对类的实例化对象进行一些初始化操作,如增加一个属性,修改一个属性的值,需要借助类的构造器 写 this.xxx=xxx即可

案例:页面展示天气炎热或凉爽的文字,当点击文字时,改变文字内容

js 复制代码
<body>
	<!-- 准备好一个"容器" -->
	<div id="test"></div>
	
	<!-- 引入react核心库 -->
	<script type="text/javascript" src="../js/react.development.js"></script>
	<!-- 引入react-dom,用于支持react操作DOM -->
	<script type="text/javascript" src="../js/react-dom.development.js"></script>
	<!-- 引入babel,用于将jsx转为js -->
	<script type="text/javascript" src="../js/babel.min.js"></script>

	<script type="text/babel">
		//1.创建组件
		class Weather extends React.Component{
			
			//构造器调用几次? ------------ 1次
			constructor(props){
				super(props)
				//初始化状态
				this.state = {isHot:false,wind:'微风'}
						}

		render(){
				//读取状态
				const {isHot,wind} = this.state
				return <h1>今天天气很{isHot ? '炎热' : '凉爽'},{wind}</h1>
			}
		}
		//2.渲染组件到页面
		ReactDOM.render(<Weather/>,document.getElementById('test'))
				
	</script>
</body>

到这里,都没什么难度,接下来我们要给这段文字添加一个点击事件,当点击文字的时候,文字发生改变,在做该操作之前,我们先来解决React中的小问题

小细节

我们把代码撰写如下:给文字加一个click事件,按理说这样没问题,但是我们看效果

js 复制代码
<body>
		<script type="text/babel">
		//1.创建组件
		class Weather extends React.Component{
			constructor(props){
				super(props)
				this.state = {isHot:false,wind:'微风'}
						}

		render(){
				const {isHot,wind} = this.state
				return <h1  onClick={demo()}>今天天气很{isHot ? '炎热' : '凉爽'},{wind}</h1>
			}
		}
		//2.渲染组件到页面
		ReactDOM.render(<Weather/>,document.getElementById('test'))
		function demo(){
					console.log('我被点击了');
				}		
	</script>
</body>

这说明你不是把demo函数赋给了点击事件,而是把demo函数运行完的返回值赋给了点击事件,由于demo函数中没有return 任何东西,因此就是undefined,因此不生效,此处小细节需要注意下。 我们只需要这样写,就可以了:

js 复制代码
	return <h1  onClick={demo}>今天天气很{isHot ? '炎热' : '凉爽'},{wind}</h1>

添加点击事件

this的指向问题

我们加一个changeWeather事件,如下所示:

js 复制代码
<script type="text/babel">
//1.创建组件
class Weather extends React.Component{
	constructor(props){
	super(props)
		this.state = {isHot:false,wind:'微风'}
	}

render(){
	const {isHot,wind} = this.state
	return <h1  onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'},{wind}</h1>
	}
        changeWeather(){
         console.log(this.state.isHot)
        }
	}
//2.渲染组件到页面
	ReactDOM.render(<Weather/>,document.getElementById('test'))
	</script>

而当我们这样写完代码,发现竟然报错了,这里说明this是undefined,这是为何呢?

我们在changeWeather中打印this,发现真的是undefined,因为这个changeWeather不是通过组件实例调用的

解决方案1:

其实加一行代码就能解决,我们这么加

解决方案2:

基于解决方案1,我们可得到最终的解决方案2

因此最后精简之后的代码为:

js 复制代码
<script type="text/babel">
//1.创建组件
class Weather extends React.Component{
//初始化状态
state = {isHot:false,wind:'微风'}
render(){
const {isHot,wind} = this.state
return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'},{wind}</h1>
}
//自定义方法------------要用赋值语句的形式+箭头函数
changeWeather = ()=>{
const isHot = this.state.isHot
this.setState({isHot:!isHot}) 
}
}
//2.渲染组件到页面
ReactDOM.render(<Weather/>,document.getElementById('test'))			
</script>

state中setState

在上面的案例中,我们不能直接修改isHot的数据,比如:this.state.isHot=!this.state.isHot,这样写了之后,数据虽然发生了变化,但是视图并没有更新,这是因为没有触发React的响应式原理,因此要借助setState来写,即:this.setState({isHot:!isHot})

state总结

核心

  1. state是组件对象最重要的属性, 值是对象(可以包含多个key-value的组合)

  2. 组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)

难点

  1. 组件中render方法中的this为组件实例对象

  2. 组件自定义的方法中this为undefined,如何解决?

a) 强制绑定this: 通过函数对象的bind()

b) 箭头函数

  1. 状态数据,不能直接修改或更新
相关推荐
也无晴也无风雨33 分钟前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
Martin -Tang1 小时前
Vue 3 中,ref 和 reactive的区别
前端·javascript·vue.js
FakeOccupational3 小时前
nodejs 020: React语法规则 props和state
前端·javascript·react.js
放逐者-保持本心,方可放逐3 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
曹天骄4 小时前
next中服务端组件共享接口数据
前端·javascript·react.js
阮少年、4 小时前
java后台生成模拟聊天截图并返回给前端
java·开发语言·前端
郝晨妤5 小时前
鸿蒙ArkTS和TS有什么区别?
前端·javascript·typescript·鸿蒙
AvatarGiser6 小时前
《ElementPlus 与 ElementUI 差异集合》Icon 图标 More 差异说明
前端·vue.js·elementui
喝旺仔la6 小时前
vue的样式知识点
前端·javascript·vue.js
别忘了微笑_cuicui6 小时前
elementUI中2个日期组件实现开始时间、结束时间(禁用日期面板、控制开始时间不能超过结束时间的时分秒)实现方案
前端·javascript·elementui