react18之 02 函数组件与类组件 父子props传值、props-type对props的限制、ref获取dom节点
props
1:函数组件
1-1 函数组件传值
1-1-1 父组件
import React, { Component } from 'react' ;
import Fat from "./Fat" ;
export default class app extends Component {
state = {
name : '我是app'
}
componentDidMount ( ) { }
changeName = ( ) => {
let { name } = this . state
name = name + '_'
this . setState ( { name} )
}
render ( ) {
const { name } = this . state
return (
< div>
app
< Fat name= { name} changeName= { this . changeName} > < / Fat>
< / div>
)
}
}
1-1-2 子组件 Fat.jsx
import React, { useEffect } from 'react' ;
export default function Fat ( props ) {
const { name, changeName } = props
console. log ( 'props' , props) ;
useEffect ( ( ) => {
console. log ( '函数组件来咯' )
} , [ ] )
const changeName1 = ( ) => {
changeName ( )
}
return (
< div className= 'content' >
Fat - { name }
< div>
我是修改父组件app的 < button onClick= { changeName1} > 修改< / button>
< / div>
< / div>
)
}
1-1-3 上述的效果
2:类组件
2-1 类组件案例 react 之简单的评论功能实现(增删)
app.jsx
import React, { Component } from "react" ;
import Add from "./Add" ;
import List from "./List" ;
export default class App extends Component {
state = {
list : [ ] ,
}
addContent = ( params ) => {
let { list} = this . state
list. push ( params)
this . setState ( {
list
} )
}
removeItem = ( id ) => {
let { list} = this . state
list = list. filter ( item => item. id !== id)
this . setState ( {
list
} )
}
render ( ) {
const { list } = this . state
return (
< div className= "App" >
< Add addContent= { this . addContent} > < / Add>
< List list= { list} removeItem= { this . removeItem} > < / List>
< / div>
) ;
}
}
Add.jsx
使用prop-types 去校验父组件传递到子组件的值!
import PtopTypes from "prop-types" ;
import React, { Component } from "react" ;
export default class Add extends Component {
static props = {
addContent : PtopTypes. func. isRequired
}
state = {
username : "" ,
content : "" ,
id : ''
} ;
usernameChange = ( event ) => {
let username = event. target. value
this . setState ( { username} )
} ;
contentChange = ( event ) => {
let content = event. target. value
this . setState ( { content} )
} ;
submit = ( ) => {
let submitObj = this . state;
this . props. addContent ( { ... submitObj, id : + new Date ( ) } )
this . setState ( {
username : "" ,
content : "" ,
id : ''
} )
}
render ( ) {
let { username, content } = this . state;
return (
< div className= "App" >
< div>
< div >
用户名:
< input type= "text" placeholder= "用户名" value= { username} onChange= { this . usernameChange} > < / input>
< / div>
< div style= { { margin : '10px 0' } } >
内容:
< textarea placeholder= "内容" value= { content} onChange= { this . contentChange} > < / textarea>
< / div>
< button onClick= { this . submit} >
提交
< / button>
< / div>
< / div>
) ;
}
}
List.jsx
import PtopTypes from "prop-types" ;
import React, { Component } from "react" ;
import ListItem from "./ListItem" ;
export default class List extends Component {
static props = {
list : PtopTypes. object. isRequired,
removeItem : PtopTypes. func. isRequired,
}
render ( ) {
const { list, removeItem } = this . props
return (
< div>
{
list. map ( ( item, idx ) => {
return (
< ListItem itemData= { item} key= { idx} removeItem= { removeItem} > < / ListItem>
)
} )
}
< / div>
) ;
}
}
ListItem .jsx
import PtopTypes from "prop-types" ;
import React, { Component } from "react" ;
export default class ListItem extends Component {
static props = {
itemData : PtopTypes. object. isRequired,
removeItem : PtopTypes. func. isRequired
}
delItem = ( ) => {
const { id } = this . props. itemData
this . props. removeItem ( id)
}
render ( ) {
const { itemData } = this . props
return (
< div style= { { marginBottom : "10px" , background : "#ccc" } } >
< div>
username - { itemData. username }
< / div>
< div>
content - { itemData. content }
< / div>
< button onClick= { this . delItem} > 删除< / button>
< / div>
) ;
}
}
3:props传递使用 prop-types 对参数进行限制
3-1 常规的限制
3-1-1 Props.jsx
import React, { useState } from 'react' ;
import PropsSon from "./PropsSon"
export default function Props ( props ) {
const [ count, setCount] = useState ( 0 ) ;
const name = '我是name'
const bool = true
const arr = [ 1 , 2 , 3 ]
const obj = {
name : 'pp' ,
age : 20
}
function addCount ( num ) {
const increment = num === 0 || typeof num === 'number' ? num : 1 ;
const res = count * 1 + increment;
setCount ( res)
}
return (
< div className= 'content' >
< div>
Props父组件 < button onClick= { addCount} > addCount< / button>
< / div>
< PropsSon count= { count} name= { name}
bool= { bool} addCount= { addCount}
arr= { arr} obj= { obj}
content= { < span> 我是通过element传递渲染的< / span> }
>
< div> 我是元素插槽,通过node渲染的< / div>
< / PropsSon>
< / div>
)
}
3-1-2 PropsSon.jsx
import React from 'react' ;
import PropsTypes from "prop-types"
export default function PropsSon ( props ) {
const { count, name, bool, addCount, arr, obj, children, content } = props
function addCountSon ( ) {
addCount ( 2 )
}
return (
< div className= 'content' >
PropsSon子组件
< div>
count - { count} < br/ >
name - { name} < br/ >
bool - { bool ? 'true' : 'false' } < br/ >
addCount - 修改父组件的数据 < button onClick= { addCountSon} > addCount+ 2 < / button> < br/ >
arr - { arr} < br/ >
obj - { obj. name} - { obj. age} - { obj. sex} < br/ >
children - { children } < br/ >
content - { content} < br/ >
< / div>
< / div>
)
}
PropsSon. propTypes = {
xxx : PropTypes. oneOfType ( [ PropTypes. number, PropTypes. string] ) , 支持number和string类型
count : PropsTypes. number. isRequired,
name : PropsTypes. string,
bool : PropsTypes. bool,
addCount : PropsTypes. func. isRequired,
arr : PropsTypes. array,
obj : PropsTypes. shape ( {
name : PropsTypes. string. isRequired,
age : PropsTypes. number. isRequired,
sex : PropsTypes. string,
} ) . isRequired,
children : PropsTypes. node,
content : PropsTypes. element,
} ;
PropsSon. defaultProps = {
count : 0 ,
bool : false ,
obj : {
name : 'pp' ,
age : 20 ,
sex : '男'
}
} ;
3-1-3 效果
ref 调用子组件的方法 与 获取子组件的数据
类组件
app.jsx 父组件
import React, { Component } from 'react' ;
import SonFuc from "./fucSon" ;
import Son from "./son" ;
export default class app1 extends Component {
childRef = React. createRef ( )
childFucRef = null
handleNameUpdate = ( updatedName ) => {
console. log ( 'updatedName' , updatedName) ;
}
chanegSonName = ( ) => {
this . childRef. current && this . childRef. current. changeName ( this . handleNameUpdate)
}
chanegSonTest = ( ) => {
this . childFucRef && this . childFucRef. test ( )
const res = this . childFucRef. getTestName ( )
console. log ( '拿到子组件的数据name' , res) ;
}
componentDidMount ( ) { }
render ( ) {
return (
< div>
< Son ref= { this . childRef} > < / Son>
< button onClick= { this . chanegSonName} > app父组件调用子组件方法< / button>
< div> -- -- -- -- 分割线-- -- -- < / div>
< SonFuc ref= { ref => this . childFucRef = ref} > < / SonFuc>
< button onClick= { this . chanegSonTest} > app父组件调用子组件方法< / button>
< / div>
)
}
}
son.jsx 子组件
import React, { Component } from 'react' ;
export default class son extends Component {
state = {
name : '我是son的name'
}
changeName = ( cb ) => {
let { name } = this . state
name = name + "1"
this . setState ( { name } , ( ) => {
cb ( this . state. name) ;
} ) ;
}
componentDidMount ( ) { }
render ( ) {
let { name } = this . state
return (
< div> son
name - { name}
< / div>
)
}
}
效果
函数组件
app.jsx
import React, { Component } from 'react' ;
import SonFuc from "./fucSon" ;
import Son from "./son" ;
export default class app1 extends Component {
childRef = React. createRef ( )
childFucRef = null
handleNameUpdate = ( updatedName ) => {
console. log ( 'updatedName' , updatedName) ;
}
chanegSonName = ( ) => {
this . childRef. current && this . childRef. current. changeName ( this . handleNameUpdate)
}
chanegSonTest = ( ) => {
this . childFucRef && this . childFucRef. test ( )
const res = this . childFucRef. getTestName ( )
console. log ( '拿到子组件的数据name' , res) ;
}
componentDidMount ( ) { }
render ( ) {
return (
< div>
< Son ref= { this . childRef} > < / Son>
< button onClick= { this . chanegSonName} > app父组件调用子组件方法< / button>
< div> -- -- -- -- 分割线-- -- -- < / div>
< SonFuc ref= { ref => this . childFucRef = ref} > < / SonFuc>
< button onClick= { this . chanegSonTest} > app父组件调用子组件方法< / button>
< / div>
)
}
}
fucSon.jsx 子组件
import React, { forwardRef, useImperativeHandle, useState } from 'react' ;
const FucSonRef = forwardRef ( ( props, ref ) => {
let [ testname, setName] = useState ( 'testname' )
useImperativeHandle ( ref, ( ) => ( {
test,
testname,
getTestName
} ) ) ;
const test = ( ) => {
testname = testname + "1"
setName ( testname)
}
const getTestName = ( ) => {
return testname
}
return (
< div>
funcson组件 - testname { testname}
< / div>
)
} )
export default FucSonRef;
效果