react学习笔记(6) - 函数式组件中的属性(props)、状态VS属性以及受控组件于非受控组件
函数式组件中的属性(props
)
- 函数式组件中的
props
(属性)与类组件还是有点不同的,因为函数式组件没有this
指向,但是却可以有形参传入,因此props
属性就是以形参传入的方式传递给子组件的,且函数式组件设置属性默认值和属性验证的方式与类组件的第二种方法非常的相似,都是以函数式组件名.defaultProps
设置默认属性和以函数式组件名.propTypes
设置属性校验,如下所示:
代码展示
- 父组件
import React, { Component } from 'react' |
- 子组件(函数式)
import React from 'react' |
状态VS
属性
相似点
:都是纯js
对象,都会触发render
更新,都具有确定性(状态/属性相同,结果相同)不同点:
- 属性能从父组件获取,状态不能
- 属性可以由父组件修改,状态不能
- 属性能在内部设置默认值,状态也可以,设置方式不一样
- 属性不在组件内部修改,状态要在组件内部修改
- 属性能设置子组件初始值,状态不可以
- 属性可以修改子组件的值,状态不可以
详细说明:
state
的主要作用是用于组件保存、控制、修改自己的可变状态。state
在组件内部初始化,可以被组件自身修改,而外部不能访问也不能修改。你可以认为state
是一个局部的、只能被组件自身控制的数据源。state
中状态可以通过this.setState()
方法更新,且每一次状态更新(setState
调用都会使得组件重新渲染)props
的主要作用是让使用该组件的父组件可以传入参数来配置该组件。它是外部传进来的配置参数,组件内部无法控制也无法修改。除非外部组件主动传入新的props
,否则组件的props
永远保持不变。没有
state
的组件叫无状态组件(stateless component
),设置了state
的组件叫做有状态组件(stateful component
),因为状态会带来管理的复杂性,因此我们更加推崇多地写无状态组件,少写有状态组件。这样会降低代码维护的难度,也会在一定程度上增强组件的可复用性。
表单中的受控组件
与非受控组件
什么是受控组件
与非受控组件
- 可以广义的认为:页面中所有
输入类的DOM
如果是现用现取
得称为非受控组件
,而通过setState
将输入的值维护到state
中,需要时再从state
获取,数据就受到了state
得控制,这样的就是受控组件
。或者React
组件的数据渲染是否被调用者传递的props
完全控制,控制则为受控组件
,否则非受控组件
。
受控组件
在使用表单来收集用户输入时,例如<input>
、<select>
、<textarea>
等元素都要绑定一个change
事件,当表单状态发生变化时,就会触发onChange
事件,更新组件的state
。这种组件为受控组件
,在受控组件中,组件渲染出的状态与它的value
或checked
属性相对应,react
通过这种方法消息组件的局部状态,是整个状态可控。
在React
中定义了一个input
输入框的话,它并没有类似于Vue
里v-model
的这种双向绑定功能,也就是说我们并没有一个指令能够将数据和输入框结合起来,用户在输入框中输入内容,然后数据同步更新。
import React, { Component } from 'react' |
用户在界面上的输入框输入内容时,它是自己维护了一个state
,这个state
并不是我们平常看见的this.state
,而是每个表单元素上抽象的state
,这样的话就能根据用户的输入自己进行UI
上的更新,如果我们想要控制输入框的内容,而输入框的内容取决的是input
中的value
属性,那么我们可以在this.state
中定义一个名为inputValue
的属性,并将input上的value指定为这个属性。
但是这时候你会发现input
的内容是只读的,因为value
会被我们的this.state.inputValue
所控制,当用户输入新的内容时,this.state.inputValue
并不会自动更新,这样的话input
内的内容也就不会变了,此时控制台通常会抛出一个Warning
。
您为表单字段提供了一个没有onChange
处理程序的value
属性,这将呈现只读字段,如果字段应该是可变的,请使用defaultValue
,否则请设置onChange
或readOnly
。
这段Warning
其实给出了对于这个问题的解决方案,我们只需要对组件的onChange
事件来监听输入内容的改变并使用setState
更新this.state.username
即可,如此我们在当前组件中能够控制这个表单元素的值,这就是受控组件。
import React, { Component } from 'react' |
- 结果展示:
但是这种受控组件
因为是存在弊端的,尽管此时Input
组件本身是一个受控组件,但与之相对的调用方(父级组件
)失去了更改Input
组件值的控制权,所以对调用方(父级组件
)而言,Input
组件是一个非受控组件,也就是说这个受控组件
无法实现数据的传输,不仅如此,表单元素的值都是由当前的React组件
(state
)进行管理,当有多个输入框,或者多个这种组件时,如果想同时获取到全部的值就必须每个都编写事件处理函数,这会让代码看起来很臃肿,所以为了解决这些情况,出现了非受控组件。
非受控组件
如果表单元素并不经过state
或没有value
或checked
属性时,而是通过ref
修改或者直接操作DOM
,那么它的数据无法通过state
控制,这就是非受控组件。
可以认为,非受控组件就是具有属性不受当前组件控制
的组件
import React, { Component } from 'react' |
- 结果展示:
总结
受控组件
- 每当表单的状态发生变化时,都会被写入到组件的
state
中。 - 在受控组件中,组件渲染出的状态与它的
value
或checked
相对应。 react
受控组件更新state
的流程:- 通过在初始
state
中设置表单的默认值。 - 每当表单的值发生变化时,调用
onChange
事件处理器。 - 事件处理器通过合成对象
event
拿到改变后的状态,并更新应用的state
。 setState
触发视图的重新渲染,完成表单组件值的更新。
- 通过在初始
非受控组件
如果一个表单组件没有
value
或者checked
就可以称为非受控组件。非受控组件是一种反模式,它的值不受组件自身的
state
或props
控制。通常需要为其添加
ref
属性来访问渲染后的底层DOM
元素。可通过添加
defaultValue
指定默认value
值。