1鉴逞、屬性(props)
組件間傳值构捡,在React中是通過只讀屬性 props 來完成數(shù)據(jù)傳遞的壳猜。
props:接受任意的入?yún)⑼嘲猓⒎祷赜糜诿枋鲰撁嬲故緝?nèi)容的 React 元素。
import React, { Component, Fragment } from 'react'
import ReactDOM from 'react-dom'
class Title extends Component {
render () {
return (
<h1>歡迎進(jìn)入{this.props.name}的世界</h1>
)
}
}
const Content = (props) => {
return (
<p>{props.name}是一個構(gòu)建UI的庫</p>
)
}
class App extends Component {
render () {
return (
<Fragment>
<Title name="React" />
<Content name="React.js" />
</Fragment>
)
}
}
ReactDOM.render(
<App/>,
document.getElementById('root')
)
- props默認(rèn)值
由于設(shè)置了defaultProps吹由, 不傳props也能正常運行倾鲫,如果傳遞了就會覆蓋defaultProps的值
-
類組件
import React,{Component,Fragment} from 'react'
import ReactDOM from 'react-dom'
class Title extends Component{
static defaultProps={
name:'zh'
}
render(){
return(
<h1>{{this.props.name}}</h1>
)
}
}
-
函數(shù)組件
const Content =(props)=>{
return (
<p>{{props.name}}</p>
)
}
Content.defaultProps={
name:'fasgd'
}
- props.children
我們知道使用組件的時候乌昔,可以嵌套壤追。要在自定義組件的使用嵌套結(jié)構(gòu)大诸,就需要使用 props.children 贯卦。在實際的工作當(dāng)中撵割,我們幾乎每天都需要用這種方式來編寫組件辙芍。
import React, { Component, Fragment } from 'react'
import ReactDOM from 'react-dom'
class Title extends Component {
render () {
return (
<h1>歡迎進(jìn)入{this.props.children}的世界</h1>
)
}
}
const Content = (props) => {
return (
<p>{props.children}</p>
)
}
class App extends Component {
render () {
return (
<Fragment>
<Title>React</Title>
<Content><i>React.js</i>是一個構(gòu)建UI的庫</Content>
</Fragment>
)
}
}
ReactDOM.render(
<App/>,
document.getElementById('root')
)
- prop-types檢查props
React其實是為了構(gòu)建大型應(yīng)用程序而生, 在一個大型應(yīng)用中故硅,根本不知道別人使用你寫的組件的時候會傳入什么樣的參數(shù)吃衅,有可能會造成應(yīng)用程序運行不了,但是不報錯峻呕。為了解決這個問題瘦癌,React提供了一種機(jī)制跷敬,讓寫組件的人可以給組件的props
設(shè)定參數(shù)檢查西傀,需要安裝和使用prop-types:
npm i prop-types -S
- 類型: array、bool、func肿仑、number碎税、object雷蹂、string
- React元素類型:element
- 必填項:isRequired
- 特定結(jié)構(gòu)的對象: shape({})
- 函數(shù)組件
import PropTypes from 'prop-types'
const Content=(props)=>{
let {a,b}=props
return (
<div>{a}匪煌</div>
)
}
Content.propTypes={
a:PropTypes.number,
b:PropTypes.number
}
- 類組件
import PropTypes from 'prop-types'
class Conetnt extends Component{
static propTypes={
a:PropTypes.number,
b:PropTypes.number
}
render(){
let {a,b}=this.props
return(
<div>
</div>
)
}
}
2. 狀態(tài)(state)
將state與表單項中的value值綁定在一起,有state的值來控制表單元素的值霜医,稱為受控組件肴敛。
綁定步驟:
- 在state中添加一個狀態(tài),作為表單元素的value值
- 給表單元素綁定change事件砸狞,將表單元素的值設(shè)置為state的值
- 定義state
方式一:
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class App extends Component {
state = {
name: 'React',
isLiked: false
}
render () {
return (
<div>
<h1>歡迎來到{this.state.name}的世界</h1>
<button>
{
this.state.isLiked ? '??取消' : '??收藏'
}
</button>
</div>
)
}
}
ReactDOM.render(
<App/>,
document.getElementById('root')
)
方式二(推薦):
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class App extends Component {
constructor() {
super()
this.state = {
name: 'React',
isLiked: false
}
}
render () {
return (
<div>
<h1>歡迎來到{this.state.name}的世界</h1>
<button>
{
this.state.isLiked ? '??取消' : '??收藏'
}
</button>
</div>
)
}
}
ReactDOM.render(
<App/>,
document.getElementById('root')
)
- setstate
this.props和this.state是純js對象,在vue中刀森,data屬性是利用Object.defineProperty處理過的撒强,更改data的數(shù)據(jù)的時候會觸發(fā)數(shù)據(jù)的getter和setter笙什,但是React中沒有做這樣的處理琐凭,如果直接更改的話统屈,react是無法得知的,所以腕扶,需要使用特殊的更改狀態(tài)的方法setState。
- 第一個參數(shù)可以是對象
- 可以是方法return一個對象吨掌,我們把這個參數(shù)叫做updater
- 參數(shù)是對象
this.setState({
isLiked: !this.state.isLiked
})
- 參數(shù)是方法
參數(shù)1:上一次的state
參數(shù)2:props
this.setState((prevState, props) => {
return {
isLiked: !prevState.isLiked
}
})
setState是異步的半抱,所以想要獲取到最新的state,沒有辦法獲取膜宋,就有了第二個參數(shù)窿侈,這是一個可選的回調(diào)函數(shù)
this.setState((prevState, props) => {
return {
isLiked: !prevState.isLiked
}
}, () => {
console.log('回調(diào)里的',this.state.isLiked)
})
console.log('setState外部的',this.state.isLiked)
3.屬性(props)VS狀態(tài)(state)
- 相似點:都是純js對象,都會觸發(fā)render更新秋茫,都具有確定性(狀態(tài)/屬性相同史简,結(jié)果相同)
- 不同點:
- 屬性能從父組件獲取,狀態(tài)不能
- 屬性可以由父組件修改肛著,狀態(tài)不能
- 屬性能在內(nèi)部設(shè)置默認(rèn)值圆兵,狀態(tài)也可以
- 屬性不在組件內(nèi)部修改,狀態(tài)要改
- 屬性能設(shè)置子組件初始值衙傀,狀態(tài)不可以
- 屬性可以修改子組件的值抬吟,狀態(tài)不可以
state
- 作用:用于組件保存、控制统抬、修改自己的可變狀態(tài)火本。
- 組件內(nèi)部初始化,可以被組件自身修改聪建,而外部不能訪問也不能修改钙畔。
- 中狀態(tài)可以通過 this.setState方法進(jìn)行更新,setState 會導(dǎo)致組件的重新渲染金麸。
props
- 作用:讓使用該組件的父組件可以傳入?yún)?shù)來配置該組件擎析。
- 它是外部傳進(jìn)來的配置參數(shù),組件內(nèi)部無法控制也無法修改挥下。
- 除非外部組件主動傳入新的 props揍魂,否則組件的 props 永遠(yuǎn)保持不變
注意:盡量少地用 state,多用 props棚瘟。
如果有多個組件共享一個數(shù)據(jù)现斋,把這個數(shù)據(jù)放到共同的父級組件中來管理。
4.受控組件與非受控組件
受控組件
將state與表單項中的value值綁定在一起偎蘸,state的值來控制表單元素的值庄蹋,稱為受控組件。
步驟:
- 在state中添加一個狀態(tài)迷雪,作為表單元素的value值
- 給表單元素綁定change事件限书,將表單元素的值設(shè)置為state的值
<input type="text" value={this.state.username} onChange={this.inputChange.bind(this)} />
注:多表單元素需優(yōu)化事件方法
this.setState({
[e.target.name]: e.target.value
})
非受控組件
沒有和state數(shù)據(jù)源進(jìn)行關(guān)聯(lián)的表單項,而是 借助ref章咧,使用元素DOM方式獲取表單元素值
步驟:
- 調(diào)用 React.createRef() 方法創(chuàng)建ref對象
- 將創(chuàng)建好的 ref 對象添加到文本框中
- 通過ref對象獲取到文本框的值
import React {Component} from 'react' //1
export default class User extends Component {
constructor(props){
super(props)
<!-- 定義一個引用 -->
this.username=React.createRef() //2
}
render(){
return{
<div>
<input type='text' ref={this.username}/>//3
<button onClick={this.addUser.bind(this)}></button>
</div>
}
}
addUser(){
console.lof(this.username.current.value)//4
}
}