ref 转发:
子组件是函数组件时 父组件需要引用组件的Ref 对象时使用ref转发
Father:
import {PureComponent, createRef} from 'react'
import Son from './Son';
class Father extends PureComponent {
// 创建 一个 Son组件的ref
SonRef = createRef();
render() {
return (
<div>
<h1>Father组件: ref转发</h1>
<button onClick={e=>this.handleRef()}>ref查看</button>
<hr/>
<Son ref={this.SonRef}/>
</div>
)
}
handleRef(){
console.log('SonRef=>', this.SonRef);
}
}
export default Father;
Son:
import { memo, forwardRef } from 'react';
/*
memo 与 forwardRef 同时出现 使用memo函数包裹 forwardRef函数
*/
const Son = (props, sonRef) => {
return (
<div ref={sonRef}>
<h1>Son组件</h1>
<button>点击</button>
</div>
)
}
export default memo(forwardRef(Son));
案例二:
获取自定义组件标签体之内的标签元素, react 会封装在props children 属性中
Father:
import {PureComponent} from 'react'
import Son from './Son';
class Father extends PureComponent {
render() {
return (
<div>
<h1>Father组件: 模拟插槽</h1>
<button onClick={e=>this.handleRef()}>ref查看</button>
<hr/>
<Son>
<h1>我是h1</h1>
<h3>我是h3</h3>
<h6>我是h6</h6>
</Son>
</div>
)
}
handleRef(){
console.log('SonRef=>', this.SonRef);
}
}
export default Father;
Son:
import { PureComponent } from 'react'
export class Son extends PureComponent {
render() {
console.log('son props=>', this.props);
return (
<div>
<h1>Son组件</h1>
{
this.props.children
}
<button>点击</button>
</div>
)
}
}
export default Son;
案例三:
Father
import {PureComponent} from 'react'
import Son from './Son';
/*
获取自定义组件标签体之内的标签元素, react 会封装在props children 属性中
*/
class Father extends PureComponent {
leftSlot = (
<div>
<h1>我是h1</h1>
<h3>我是h3</h3>
</div>
);
rightSlot = (
<h6>我是h6</h6>
)
render() {
return (
<div>
<h1>Father组件: 模拟插槽Slot</h1>
<button onClick={e=>this.handleRef()}>ref查看</button>
<hr/>
<Son leftSlot={this.leftSlot} rightSlot={this.rightSlot}/>
</div>
)
}
handleRef(){
console.log('SonRef=>', this.SonRef);
}
}
export default Father;
Son:
import { PureComponent } from 'react'
export class Son extends PureComponent {
render() {
console.log('son props=>', this.props);
return (
<div>
<h1>Son组件</h1>
<button>点击</button>
<div className='d-flex'>
<div>
左边:
{
this.props.leftSlot
}
</div>
<div>
右边:
{
this.props.rightSlot
}
</div>
</div>
</div>
)
}
}
export default Son;
案例四:
注: Hook API 只能在函数组件内使用; Hook API 不要放在 循环、条件判断中
useState : 保存与修改 函数组件内的状态(state)
useContext: useContext(context对象名称) :返回值 获取对象context 对象中的 value属性值
useEffect 与 useLayoutEffect
useRef 与 useImperativeHandle
useMemo 与 useCallback
useReducer : 通过纯函数reducer 修改state 注:不能取代 redux
useDebugValue: 在自定义的Hook函数中 给默写属性值 设置一个特殊的标记信息
useId : 在 SSR 环境下使用 , 给渲染的DOM 节点分配id
useTransition 与 useDeferredValue
useRoutes 与 useOutlet
自定义Hook
Father
import {useState} from 'react'
const Father = () => {
/*
函数组件: 每次执行 组件状态更新时会将整个内部的代码全部执行一次
useState(initValue): initValue参数: 初始状态数据值
useState(()=>{ 初始状态的业务代码 })
useState: 返回值 数组类型 元素一 : 初始化状态变量 元素二: 改变状态的函数对象
*/
const [count, setCount] = useState(0);
let state = 0;
const add = e => {
setCount(count+1);
state = state +1;
console.log('state=>', state);
}
console.log('组件渲染...............');
return (
<div>
<h1>Father组件: useState</h1>
<h3>count:{count}</h3>
<h3>state:{state}</h3>
<button onClick={add}>+1</button>
</div>
)
}
export default Father
Father1:
import {useState} from 'react';
import { v4 as uuid } from 'uuid';
const Father1 = () => {
const [arr1, setArr1] = useState(()=> [1,2,3] );
const [arr2, setArr2] = useState([100,101]);
const add1 = e => {
setArr1([...arr1, new Date().getTime()]);
}
const add2 = e => {
setArr2([...arr2, new Date().getTime()]);
}
return (
<div>
<h1>Father1:多个状态</h1>
<div className='d-flex'>
<div>
<button onClick={e=>add1(e)}>arr1新增</button>
<h3>Arr1:</h3>
<ul>
{
arr1.map( item => (
<li key={uuid()}>{item}</li>
) )
}
</ul>
</div>
<div className='mx-2'>
<button onClick={add2}>arr2新增</button>
<h3>Arr2:</h3>
{
arr2.map( item => (
<li key={uuid()}>{item}</li>
) )
}
</div>
</div>
</div>
)
}
export default Father1
案例五:
CompContext.js
import { createContext } from 'react';
/*
创建 上下文 Context
*/
export const FatherContext = createContext();
export const SonContext = createContext();
Father:
import {memo} from 'react'
import Son from '../案例6/Son';
import { FatherContext } from './CompContext';
const Father = props => {
return (
<div>
<h1>Father组件: useContext</h1>
<hr/>
<FatherContext.Provider value={{name: '父组件'}}>
<Son/>
</FatherContext.Provider>
</div>
)
}
export default memo(Father);
Son:
import {memo} from 'react';
import { SonContext } from './CompContext';
import Son1 from './Son1';
const Son = () => {
return (
<div>
<h1>Son组件:</h1>
<hr/>
<SonContext.Provider value={[1,2,3]}>
<Son1/>
</SonContext.Provider>
</div>
)
}
export default memo(Son);
Son1:
import {memo, useContext} from 'react'
import {FatherContext, SonContext} from './CompContext';
const Son1 = () => {
// 获取 FatherContext 对应的value 属性值
const FatherContextValue = useContext(FatherContext);
// 获取 SonContextValue 对应的value 属性值
const SonContextValue = useContext(SonContext);
return (
<div>
<h1>Son1组件:</h1>
<h3>FatherContextValue: {FatherContextValue.name}</h3>
<h3>SonContextValue: {SonContextValue}</h3>
</div>
)
}
export default memo(Son1);
案例六:
/*
useEffect:
1、 充当函数组件中的生命周期函数
2、执行的时间点 挂载之后、状态更新之后、销毁之前
useEffect(() => {
挂载之后、状态更新之后执行的业务代码
return () => {
销毁之前执行的业务代码
}
}, [依赖项列表]);
依赖项:决定 useEffect 是否执行 依赖项列表中的值都没有变化则不执行useEffect 函数, 依赖值列表中任意的一个值发生改变则重新执行useEffect
依赖项列表: 如果写出 [] useEffect在函数组件第一次初始化执行 后续则不会再执行
依赖项列表参数没有写, 每次都会执行(挂载之后、更新之后)
*/
import {useState, useEffect} from 'react'
import Son from './Son';
const Father = () => {
const [num, setnum] = useState(0);
const [count, setcount] = useState(0);
const [isShow, setIsShow] = useState(true);
useEffect(() => {
console.log('执行useEffect =>', new Date() ,' num=>',num);
}, [num]);
return (
<div>
<h1>Father组件: useEffect</h1>
<h3>{num} --- {count}</h3>
<button onClick={e=>setnum(num+1)}>num</button>
<button onClick={e=>setcount(count+1)}>count</button>
<button onClick={e=>setIsShow(!isShow)}>隐藏/显示Son组件</button>
<hr/>
{
isShow ? <Son/> : ''
}
</div>
)
}
export default Father
Son:
import { useEffect } from 'react'
const Son = () => {
useEffect(() => {
console.log('Son组件执行useEffect......');
return () => {
console.log('Son组件销毁之前执行清理工作........');
}
})
return (
<div>Son........</div>
)
}
export default Son