受控组件的概念:
受控组件使用步骤
import React from 'react'
/**
* 1. input 元素
* 2. textarea 元素
* 3. select 元素
* 4. checkbox 元素
*/
export default class App extends React.Component {
state = {
value: '',
content: '',
selectValue: '',
checkbox: false
}
change = (e) => {
// 2. 根据表单元素类型获取对应值
// 2.1 获取表单元素
const target = e.target
// 2.2 target.type --- 表单元素类型
// 由于复选框控制的值变化 和 其他 input 框不一样,所以这里先判断他的类型 然后 从而拿到对应的值
const value = target.type === 'checkbox' ? target.checked : target.value
// 3. 通过 [name] 来修改对应的state
// 3.1 target.name -- 获取元素的名称
const name = target.name
// 3.1 根据获取的 name 值修改 state
this.setState({
[name]: value
})
}
render () {
return (
<div>
{/* 1. 给表单元素添加name属性,名称与 state 相同 */}
<input name="value" type="text" value={ this.state.value } onChange={ this.change } />
<textarea name="content" value={this.state.content} onChange={ this.change } cols="10" rows="3"></textarea>
<select name="selectValue" value={ this.state.selectValue } onChange={ this.change }>
<option value="ys">亚瑟</option>
<option value="dj">妲己</option>
<option value="dw">典韦</option>
</select>
<input name="checkbox" type="checkbox" checked={ this.state.checkbox } onChange={ this.change } />
<button onClick={() => this.setState({
value: ''
})}>11</button>
</div>
)
}
}
非受控组件
借助于 ref,使用原生 DOM 方式来获取表单元素值
ref 的作用:获取 DOM 和组件
非受控组件使用步骤
调用 React.createRef()方法创建一个 ref 对象
将创建好的 ref 对象添加到文本框中
通过 ref 对象获取到文本框的值
import React from 'react'
export default class App extends React.Component {
constructor () {
super()
this.state = {
val: ''
}
// 调用 React.createRef() 方法创建一个 ref 对象
this.txtRef = React.createRef()
}
handleChange = () => {
// 通过 ref 对象获取到文本框的值
console.log(this.txtRef.current.value)
}
render() {
return (
<div>
{/* 将创建好的 `ref` 对象添加到文本框中 */}
<input type="text" ref={ this.txtRef } onChange={this.handleChange} />
</div>
)
}
}
概念:
组件是独立且封闭的单元,默认情况下,只能使用组件自己的数据。在组件化过程中,我们将一个完整的功能拆分成多个组件,以更好的完成整个应用的功能。而在这个过程中,多个组件之间不可避免的要共享某些数据。为了实现这些功能,就需要打破组件的独立封闭性,让其与外界沟通。这个过程就是组件通讯。
(1)组件中的 props 使用
// 类组件
import React from 'react'
export default class App extends React.Component {
render () {
return (
<div>
<div>{ this.props.name }</div>
</div>
)
}
}
// 函数组件
export default function App (props) {
return (
<div>
<div>{ props.name }</div>
</div>
)
}
// 传递数据
ReactDOM.render(<App name="亚瑟" />, document.getElementById('root'))
(2) 组件的 props - 特点
// 组件的特点
export default class App extends React.Component {
constructor (props) {
// 使用类组件时,如果写了构造函数,应该将 props 传递给 super()
super(props)
console.log(props) // {name:'亚瑟',age:10,info:妲己
}
}
render () {
// props 是只读的对象,只能读取属性值,无法修改对象
// this.props.name = '百里玄策'
return (
<div>
{/* 接收任意类型值 */}
<div>{ this.props.name }</div>
<div>{ this.props.age }</div>
<div>{ this.props.info }</div>
</div>
)
}
}
// 给组件传值
ReactDOM.render(
<App
name="亚瑟"
age={10}
info={<p>妲己</p>} />,
document.getElementById('root')
)
(3)父组件传递数据给子组件
import React from 'react'
export default class App extends React.Component {
state = {
name: '亚瑟'
}
render() {
return (
// 要传递给子组件的数据
<Son name={this.state.name}></Son>
)
}
}
class Son extends React.Component {
render() {
return (
<div>
// 通过 props 来接受父组件传递过来的数据
{this.props.name}
</div>
)
}
}
(4) 子组件传递数据给父组件
思路:利用回调函数,父组件提供回调,子组件调用,将要传递的数据作为回调函数的参数
import React from 'react'
export default class App extends React.Component {
state = {
name: '亚瑟'
}
// 1. 父组件提供一个回调函数
getSonData = (data) => {
// 4. 将子组件的数据作为参数传递给回调函数
console.log('接收到父组件传递过来的数据:' + data)
}
render() {
return (
{/* 2. 将该函数作为属性的值,传递给子组件 */}
<Son getSonData={this.getSonData} name={this.state.name}></Son>
)
}
}
class Son extends React.Component {
state = {
age: 18
}
handleClick = () => {
// 3. 子组件通过 props 调用回调函数
this.props.getSonData(this.state.age)
}
render() {
return (
<div>
<button onClick={this.handleClick}>子组件向父组件传值</button>
</div>
)
}
}
(5) 兄弟组件通讯
思想:状态提升
import React from 'react'
export default class App extends React.Component {
state = {
name: '亚瑟',
age: 0
}
getSonData = (data) => {
// 2. 父级将元素赋值给 data
this.setState({
age: data
})
}
render() {
return (
<div>
<Son1 getSonData={this.getSonData} name={this.state.name}></Son1>
{/* 3. 将值传递给另一个子组件 */}
<Son2 age={ this.state.age }></Son2>
</div>
)
}
}
// 第一个子组件
class Son1 extends React.Component {
state = {
age: 18
}
handleClick = () => {
// 1. 通过 props 将值传递给最近的父级
this.props.getSonData(this.state.age)
}
render() {
return (
<div>
<button onClick={this.handleClick}>子组件向父组件传值</button>
</div>
)
}
}
// 第二个子组件
class Son2 extends React.Component {
render() {
return (
<div style={{ marginTop: '10px' }}>
兄弟组件传递的数据: { this.props.age }
</div>
)
}
}
(6)context 使用的步骤:
import React from 'react'
const { Provider, Consumer } = React.createContext()
export default class App extends React.Component {
state = {
name: '亚瑟',
age: 0
}
render() {
return (
<Provider value={this.state.name}>
<div>
<Son1></Son1>
</div>
</Provider>
)
}
}
// 子组件
class Son1 extends React.Component {
render() {
return (
<div>
<Son2></Son2>
</div>
)
}
}
// App 的孙子组件 son1的子组件
class Son2 extends React.Component {
render() {
return (
<Consumer>
{
data => (
<div>
接收祖先节点的数据:{ data }
</div>
)
}
</Consumer>
)
}
}
(1) children 属性
// children 属性基本使用
import React from 'react'
export default class App extends React.Component {
render () {
return (
<div>
{ this.props.children }
</div>
)
}
}
// 传递 children 属性
ReactDOM.render(
<App>
我在等风,也在等你……
</App>,
document.getElementById('root')
)
// 传递函数
const handle = () => {
console.log('你好呀')
}
ReactDOM.render(
<App>
{
handle()
}
</App>,
document.getElementById('root')
)
// 可以传递任何值 甚至也可以传递一个组件
(2)props 校验
import React from 'react'
// 导入 props 校验的包
import PropTypes from 'prop-types'
export default class App extends React.Component {
render () {
return (
<div>
{ this.props.arr }
</div>
)
}
}
// 这里表示 App 组件接受了一个 arr 传递过来的必须是一个数组类型的值
App.propTypes = {
arr: PropTypes.array
}
(3) props 约束规格
(4)props 默认值
import React from 'react'
import PropTypes from 'prop-types'
export default class App extends React.Component {
render () {
return (
<div>
{ this.props.num }
</div>
)
}
}
// 接受 num 值 必须为数值类型的
App.propTypes = {
num: PropTypes.number
}
// 提供默认值为 18
App.defaultProps = {
num: 18
}