React函数组件用法
组件封装调用
import { useState } from 'react'
/**引入子组件Son */
import Son from './components/son'
import './App.css'
function App() {
const [count, setCount] = useState(0)
return (
<>
{count}
<br />
{/* 调用子组件Son */}
<Son />
</>
)
}
export default App
import { useCallback, useState } from "react"
const Son = ()=>{
const [sonTitle] = useState('我是子组件')
return<>
{sonTitle}
</>
}
export default Son
组件传值 父传子
使用属性的方式进行传参 子组件接受props
import { useState } from 'react'
/**引入子组件Son */
import Son from './components/son'
import './App.css'
function App() {
const [count, setCount] = useState(0)
const [fatherData,setFatherData] = useState('我是父组件的数据')
return (
<>
{count}
<br />
{/* 调用子组件Son
* @fatherData 给子组件传参
*/}
<Son fatherData={fatherData}/>
</>
)
}
export default App
import { useCallback, useState } from "react"
/**
* @fatherData
* 使用解构的形式
* 此处一定要设置默认值 不然报错概率大
*/
const Son = ({fatherData = ''})=>{
const [sonTitle] = useState('我是子组件')
return<>
{sonTitle}
{fatherData}
</>
}
export default Son
组件传值子传父
将父组件的方法以参数的形式传入到子组件 子组件调用传参即可
import { useCallback, useState } from 'react'
/**引入子组件Son */
import Son from './components/son'
import './App.css'
function App() {
const [count, setCount] = useState(0)
const [fatherData,setFatherData] = useState('我是父组件的数据')
const fatherFn = useCallback((SonProps:string):void=>{
console.log(SonProps)
})
return (
<>
{count}
<br />
{/* 调用子组件Son
* @fatherData 给子组件传参
* @fatherFn 给子组件传参
*/}
<Son fatherData={fatherData} fatherFn={fatherFn}/>
</>
)
}
export default App
import { useCallback, useState } from "react"
/**
* @fatherData
* @fatherFn 父组件传递过来的方法用于给父组件传递参数
* 使用解构的形式
* 此处一定要设置默认值 不然报错概率大
*/
const Son = ({fatherData = '',fatherFn = ():void=>{}})=>{
const [sonTitle] = useState('我是子组件')
return<>
{sonTitle}
{fatherData}
<button onClick={fatherFn.bind(null,'我是子组件传递过来的参数(bind)')}>
点我给父组件传值 bind
</button>
{/* 推荐使用 */}
<button onClick={()=>fatherFn('我是子组件传递过来的参数(箭头函数)')}>
点我给父组件传值 箭头函数
</button>
</>
}
export default Son
父组件调用子组件的方法–ref
import { useCallback, useEffect, useRef, useState } from 'react'
/**引入子组件Son */
import Son from './components/son'
import './App.css'
function App() {
const [count, setCount] = useState(0)
const [fatherData,setFatherData] = useState('我是父组件的数据')
const fatherFn = useCallback((SonProps:string):void=>{
console.log(SonProps)
})
/**
* @useRef 创建一个ref 给子组件绑定
* @current 子组件暴露出来的都在current下
*/
const refSon = useRef()
const useSonFn = useCallback(()=>{
console.log('子组件',refSon.current)
// 调用子组件的方法
refSon.current.sonFn()
})
useEffect(()=>{
// 查看子组件
console.log(refSon)
},[])
return (
<>
{count}
<button onClick={useSonFn}> 调用子组件Son的方法</button>
<br />
{/* 调用子组件Son
* @fatherData 给子组件传参
*/}
<Son ref={refSon} fatherData={fatherData} fatherFn={fatherFn}/>
</>
)
}
export default App
import { forwardRef, useCallback, useImperativeHandle, useState } from "react"
/**
* @fatherData
* @fatherFn 父组件传递过来的方法用于给父组件传递参数
* 使用解构的形式
* 此处一定要设置默认值 不然报错概率大
*/
const Son = ({fatherData = '',fatherFn = ():void=>{}},ref)=>{
const [sonTitle] = useState('我是子组件')
const sonFn = useCallback(()=>{
console.log('父组件调用了我')
})
/**
* @useImperativeHandle
* 作用和vue3的defineExpose一样, 存储需要暴露给父组件让其获取的数据和函数
*/
useImperativeHandle(ref,()=>({
sonFn,
sonTitle
}));
return<>
{sonTitle}
{fatherData}
<button onClick={fatherFn.bind(null,'我是子组件传递过来的参数(bind)')}>
点我给父组件传值 bind
</button>
<button onClick={()=>fatherFn('我是子组件传递过来的参数(箭头函数)')}>
点我给父组件传值 箭头函数
</button>
</>
}
/**
* @forwardRef
* forwardRef作用: 封装组件, 直接将ref参数加在props后面(也可以不使用, 自己props定义一下ref需要传参, 父组件一样传ref就行)
*/
export default forwardRef(Son)
总结: 父组件用useRef() 子组件需要forwardRef 封装组件并且需要useImperativeHandle(ref,()=>({ })抛出
类式组件用法
组件封装
/**
* @father组件 父组件
*/
import React, { ReactNode } from 'react'
/**引入子组件Son */
import Son from './components/son'
import './App.css'
export default class App extends React.Component{
render(): ReactNode {
return<>
{/* 父组件 */}
{/* 子组件 */}
<Son />
</>
}
}
/**
* @Son组件 子组件
*/
import React, { ReactNode } from "react"
export default class Son extends React.Component{
render():ReactNode{
return<>
我是子组件
</>
}
}
组件传值 父传子
/**
* @father组件 父组件
*/
import React, { ReactNode } from 'react'
/**引入子组件Son */
import Son from './components/son'
import './App.css'
export default class App extends React.Component{
state={
fatherData:'我是父组件传递过来的参数'
}
render(): ReactNode {
return<>
{/* 父组件 */}
{/* 子组件 */}
<Son fatherData={this.state.fatherData}/>
</>
}
}
/**
* @Son组件 子组件
*/
import React from "react"
import PropTypes from 'prop-types'
export default class Son extends React.Component{
static defaultProps: {
fatherData: string //限制fatherData必传,且为字符串
}
render(){
const {fatherData} = this.props
return<>
我是子组件
{fatherData}
</>
}
}
Son.defaultProps = {
fatherData:'' //限制fatherData必传,且为字符串
}
Son.propTypes = {
//限制fatherData必传,且为字符串(PropTypes首字母必须大写)
fatherData: PropTypes.string.isRequired
}
组件传值 子传父
/**
* @father组件 父组件
*/
import React, { ReactNode } from 'react'
/**引入子组件Son */
import Son from './components/son'
import './App.css'
export default class App extends React.Component{
state={
fatherData:'我是父组件传递过来的参数'
}
fatherFn = (data:string='')=>{
console.log('我是子组件传递过来的参数:',data)
}
render(): ReactNode {
return<>
{/* 父组件 */}
{/* 子组件 */}
<Son fatherData={this.state.fatherData} fatherFn={this.fatherFn}/>
</>
}
}
/**
* @Son组件 子组件
*/
import React from "react"
import PropTypes from 'prop-types'
export default class Son extends React.Component{
static defaultProps: {
fatherData: string, //限制fatherData必传,且为字符串
// eslint-disable-next-line @typescript-eslint/ban-types
fatherFn: Function
}
render(){
const {fatherData,fatherFn} = this.props
return<>
我是子组件
{fatherData}
<button onClick={()=>fatherFn('子组件132')}>点我给父组件传参</button>
</>
}
}
Son.defaultProps = {
fatherData:'', //限制fatherData必传,且为字符串
fatherFn:()=>{}
}
Son.propTypes = {
//限制fatherData必传,且为字符串(PropTypes首字母必须大写)
fatherData: PropTypes.string.isRequired,
fatherFn:PropTypes.func.isRequired
}
父组件调用子组件的方法 --ref
/**
* @father组件 父组件
*/
import React, { createRef, ReactNode } from 'react'
/**引入子组件Son */
import Son from './components/son'
import './App.css'
export default class App extends React.Component{
state={
fatherData:'我是父组件传递过来的参数'
}
public fatherFn = (data:string='')=>{
console.log('我是子组件传递过来的参数:',data)
}
public refSon = createRef(null)
componentDidMount(): void {
console.log(this.refSon.current)
this.refSon.current.SonFn()
}
render(): ReactNode {
return<>
{/* 父组件 */}
{/* 子组件 */}
<Son ref={this.refSon} fatherData={this.state.fatherData} fatherFn={this.fatherFn}/>
</>
}
}
/**
* @Son组件 子组件
*/
import React from "react"
import PropTypes from 'prop-types'
export default class Son extends React.Component{
static defaultProps: {
fatherData: string, //限制fatherData必传,且为字符串
// eslint-disable-next-line @typescript-eslint/ban-types
fatherFn: Function
}
public SonFn = ()=>{
console.log('我是子组件的方法')
}
render(){
const {fatherData,fatherFn} = this.props
return<>
我是子组件
{fatherData}
<button onClick={()=>fatherFn('子组件132')}>点我给父组件传参</button>
</>
}
}
Son.defaultProps = {
fatherData:'', //限制fatherData必传,且为字符串
fatherFn:()=>{}
}
Son.propTypes = {
//限制fatherData必传,且为字符串(PropTypes首字母必须大写)
fatherData: PropTypes.string.isRequired,
fatherFn:PropTypes.func.isRequired
}
兄弟组件传值–Context
// 创建并暴露Context对象
export const { Provider, Consumer } = React.createContext()
return (
<div className='grandpa'>
<h3>我是祖组件</h3>
<h4>我的用户名是:{username}</h4>
<h4>我的年龄是:{age}</h4>
<button onClick={this.changeMessage}>点我更改信息</button>
<Provider value={{ username, age }}>
<Parent />
</Provider>
</div>
)
// 导入Grandpa组件中暴露出来的Context对象的Consumer
import { Consumer } from './Grandpa'
return (
<Consumer>
{
(value) => {
return (<div className='son' >
<h3>我是子组件</h3>
<h4>我接收到的用户名是:{value.username}</h4>
<h4>我接收到的年龄是:{value.age}</h4>
</div >)
}
}
</Consumer >
)