React小记(二)_组件通信、生命周期、hooks等

10、组件通信(父=>子)

10.1 基本使用

复制代码
    1、传递方式与函数组件一致
    2、接收时通过 this.props.mes 获取
js 复制代码
import React from 'react'
class Son extends React.PureComponent{
  render() {
    return (
      <>
        <h3>子组件</h3>
        {/* 2、接收 */}
        <span>接收:{this.props.mes}</span>
      </>
    )
  }
}
class App extends React.PureComponent {
  state = {
    sonMes:'son'
  }
  render() {
    return (
      <div>
        <h2>父组件</h2>
        {/* 1、传递 */}
        <Son mes={ this.state.sonMes} />
      </div>
    )
  }
}
export default App;

10.2 类型限制

复制代码
  1、手写验证方法
  2、借助 proptypes 库
js 复制代码
// 1、props 类型限制
Son.propTypes = {
  // (1)手写
  mes: function (props) {
    if (typeof props.mes !== 'string') {
      throw new Error('mes 必须为字符串')
    }
  },
  // (2)使用库
  color:proptypes.number
}
// 2、props 默认值限制
Son.defaultProps = {
  mes: '默认值',
  color:'绿色'
}

11、插槽

复制代码
    传递html元素,借助【props.children】获取
      1、传递:写在子组件内容区域
      2、接收: this.props.children

11.1 具名插槽

js 复制代码
import React from 'react'

class Son extends React.PureComponent{
  render() {
    return (
      <>
        {/* 2、接收 */}
        <span>接收:{this.props.children}</span>
      </>
    )
  }
}

class App extends React.PureComponent {
  render() {
    return (
      <div>
        {/* 1、传递 */}
        <Son>
          <li>内容</li>
          <li>内容</li>
          <li>内容</li>
        </Son>
      </div>
    )
  }
}

export default App;

11.2 作用域插槽

复制代码
    1、父组件传递函数,函数返回值为html元素
    2、子组件调用时,传递数据,渲染jsx
js 复制代码
import React from 'react'

class Son extends React.PureComponent{
  state = {
    data:'作用域插槽'
  }
  render() {
    return (
      <>
        {/* 2、接收 */}
        {/* 作用域插槽 */}
        {this.props.slot(this.state.data)}
      </>
    )
  }
}

class App extends React.PureComponent {
  render() {
    return (
      <div>
        {/* 1、传递 */}
        <Son slot={(slot) => <div>{ slot}</div>}></Son>
      </div>
    )
  }
}

export default App;

12、组件通信(子=>父)

复制代码
  1、父组件向子组件传递方法
  2、子组件调用并传递数据
  3、父组件拿到数据
js 复制代码
import React from 'react'

class Son extends React.PureComponent{
  state = {
    data:'作用域插槽'
  }
  render() {
    return (
      <>
        {/* 2、子组件调用并传递数据 */}
        <button onClick={() => {
          this.props.onActive('data')
        }}>
          点击传递
        </button>
      </>
    )
  }
}

class App extends React.PureComponent {
  // 3、父组件拿到数据
  handle = (data) => {
    console.log('接收数据',data);
  }
  render() {
    return (
      <div>
        {/* 1、父组件向子组件传递方法 */}
        <Son onActive={this.handle} />
      </div>
    )
  }
}

export default App;

13、生命周期

13.1 生命周期介绍

复制代码
    0、渲染 render
        初次渲染 更新时执行
    1、挂载 componentDidMount
        (1)数据请求
        (2)echart绘制  
    2、更新
        shouldComponentUpdate(是否更新) 
            性能优化 PureComponent
        componentDidUpdate
    3、卸载 componentDidUnmount
        销毁定时器

13.2 更新原理

复制代码
    1、vue 
        (1)使用了【get】依赖收集,把受当前数据影响的部分收集起来
        (2)数据变动时使用【set】触发更新
    2、react
        (1)使用useState触发更新,无论数据是否改变
        (2)有性能问题

14、ref

复制代码
    1、用于获取DOM节点或者组件实例
    2、获取组件时,只能获取类组件,函数组件没有实例
    3、在挂载阶段获取ref

14.1 React.createref()

js 复制代码
import React from 'react'

// 1、声明标识变量
let identify = React.createRef()
let son = React.createRef()

class Son extends React.Component {
  f1 = () => {
    console.log('调用子组件的方法');
  }
  render() {
    return <div>子组件</div>
  }
}

class App extends React.Component {
  componentDidMount() {
    // 3、获取DOM
    console.log(identify.current);
    console.log(son.current);
    son.current.f1()
  }
  render() {
    return (
      // 2、打标识
      <div ref={identify}><Son ref={son}/></div>
    )
  }
}
export default App;

14.2 回调函数写法

复制代码
		ref={(c)=>{this.input1=c}}
      1、c 实际上为当前DOM实例
      2、将 c 挂载到this上
      3、并取名为 input1
      4、这样便可以通过this.input1 拿到该 DOM
js 复制代码
class Demo extends React.Component{
			//展示左侧输入框的数据
			showData = ()=>{
				const {input1} = this
				alert(input1.value)
			}
			//展示右侧输入框的数据
			showData2 = ()=>{
				const {input2} = this
				alert(input2.value)
			}
			render(){
				return(
					<div>
						<input ref={(a)=>{this.input1=a}} type="text" placeholder="点击按钮提示数据"/>&nbsp;
						<button onClick={this.showData}>点我提示左侧的数据</button>&nbsp;
						<input onBlur={this.showData2} ref={c => this.input2 = c } type="text" placeholder="失去焦点提示数据"/>&nbsp;
					</div>
				)
			}
		}

15、context(类似于provide和inject)

复制代码
    适用于跨级组件通信
    1、声明公用的context组件
    2、传递方:provider
    3、接收方:
      (1) consumer组件 + 作用域插槽
      (2) 静态属性contextType + this.context
js 复制代码
import React from 'react'

// 1、声明context变量
let Context = React.createContext()

class GrandSon extends React.Component {
  // 指定 contextType 读取 context
  static contextType = Context;
  render() {
    return (
      <>
        <h4>孙子组件</h4>
        {/* 3、使用方 */}
        {/* (1):consumer + 作用域插槽 */}
        <Context.Consumer>
          {(value) => <div>{ value}</div>}
        </Context.Consumer>
        {/* (2) 借助静态属性 使用 this.context 访问 */}
        <div>{this.context}</div>
      </>
    )
  }
}

class Son extends React.Component {
  render() {
    return (
      <div>
        <h3>子组件</h3>
        <GrandSon/>
      </div>
    )
  }
}

class App extends React.Component {
  state = {
    data: 'context 传递的数据'
  }
  
  render() {
    return (
      <>
        <h2>父组件</h2>
        {/* 2、传递方:provide并传递value */}
        <Context.Provider value={this.state.data}>
          <Son />
        </Context.Provider>
      </>
    )
  }
}

export default App;

16、hooks

16.1 useState

复制代码
    1、让函数组件也可以有state状态, 并进行状态数据的读写操作
    2、【语法】: 
      const [xxx, setXxx] = React.useState(initValue)  
    3、useState()说明:
      【参数】: 第一次初始化指定的值在内部作缓存
      【返回值】: 包含2个元素的数组, 第1个为内部当前状态值, 第2个为更新状态值的函数
    4、setXxx()2种写法:
      setXxx(newValue): 参数为非函数值, 直接指定新的状态值, 内部用其覆盖原来的状态值
      setXxx(value => newValue): 参数为函数, 接收原本的状态值, 返回新的状态值, 内部用其覆盖原来的状态值

16.2 useEffect

复制代码
  1、在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子)
  2、React中的副作用操作:
      发ajax请求数据获取
      设置订阅 / 启动定时器
      手动更改真实DOM
  3、语法和说明: 
      useEffect(() => { 
        // update/mount
        return () => { // 在组件卸载前执行
          // 在此做一些收尾工作, 比如清除定时器/取消订阅等
        }
      }, [stateValue]) // 如果指定的是[], 回调函数只会在第一次render()后执行
  4、可以把 useEffect Hook 看做如下三个函数的组合
        componentDidMount()
        componentDidUpdate()
        componentWillUnmount() 
  5、第二个参数填写依赖项 类似于【vue的监听】

16.3 useMemo

复制代码
    1、用于优化函数组件性能,缓存【数据】,避免不必要的计算
    2、相当于 vue 的【计算属性】
    3、根据依赖项决定是否重新计算

16.4 useCallback

复制代码
    1、用于优化函数组件性能,缓存【函数】,避免不必要的计算
    2、相当于 vue 的【计算属性】
    3、根据依赖项决定是否重新计算

16.5 useRef

复制代码
    0、与【createRef】类似,只是声明标识变量的方式不同
    1、用来获取DOM阶段
    2、用来获取之前的数据
    3、用来获取组件及组件身上的方法

16.6 useContext

js 复制代码
    1、创建context方式不变
      const Context = React.createContext()
    2、【使用方】useContext 直接接收值
      let value = useContext(Context)

17、高阶组件 Hoc (类似于vue中混入)

复制代码
    【用途】提取公用逻辑,实现复用

18、组件性能优化

复制代码
    1、问题:父组件的更新会连带子组件一起更新
    2、解决:diff算法 + 时间切片(部分更新,部分渲染)
      (1) 将任务分为许多个执行单元
      (2) 有时间 ? 接着运行执行单元 :交给浏览器更新
    3、引入fiber数据结构
      为了支持切片,引入此数据结构
      (1) 支持组件切片
      (2) 具有继续执行的能力(恢复上次进度)
    4、我们能做的
      (1) PureComponment
          避免state修改为同样的值,触发更新
      (2) Memo 结合 useMemo 、useCallback
          包裹对象、数组、方法 避免子组件更新

19、组件库

复制代码
    Ant Design
      1、Button
      2、Table 插槽
      3、定制主题 ConfigProvider
相关推荐
未来之窗软件服务2 小时前
一体化系统(九)智慧社区综合报表——东方仙盟练气期
大数据·前端·仙盟创梦ide·东方仙盟·东方仙盟一体化
陈天伟教授5 小时前
人工智能训练师认证教程(2)Python os入门教程
前端·数据库·python
信看6 小时前
NMEA-GNSS-RTK 定位html小工具
前端·javascript·html
Tony Bai6 小时前
【API 设计之道】04 字段掩码模式:让前端决定后端返回什么
前端
爱吃大芒果6 小时前
Flutter 主题与深色模式:全局样式统一与动态切换
开发语言·javascript·flutter·ecmascript·gitcode
苏打水com6 小时前
第十四篇:Day40-42 前端架构设计入门——从“功能实现”到“架构思维”(对标职场“大型项目架构”需求)
前端·架构
king王一帅6 小时前
流式渲染 Incremark、ant-design-x markdown、streammarkdown-vue 全流程方案对比
前端·javascript·人工智能
苏打水com7 小时前
第十八篇:Day52-54 前端跨端开发进阶——从“多端适配”到“跨端统一”(对标职场“全栈化”需求)
前端
Bigger7 小时前
后端拒写接口?前端硬核自救:纯前端实现静态资源下载全链路解析
前端·浏览器·vite