当前位置:   article > 正文

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

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

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

10.1 基本使用

    1、传递方式与函数组件一致
    2、接收时通过 this.props.mes 获取
  • 1
  • 2
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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

10.2 类型限制

  1、手写验证方法
  2、借助 proptypes 库
  • 1
  • 2
// 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:'绿色'
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

11、插槽

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

11.1 具名插槽

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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

11.2 作用域插槽

    1、父组件传递函数,函数返回值为html元素
    2、子组件调用时,传递数据,渲染jsx
  • 1
  • 2
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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

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

  1、父组件向子组件传递方法
  2、子组件调用并传递数据
  3、父组件拿到数据
  • 1
  • 2
  • 3
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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

13、生命周期

13.1 生命周期介绍

    0、渲染 render
        初次渲染 更新时执行
    1、挂载 componentDidMount
        (1)数据请求
        (2)echart绘制  
    2、更新
        shouldComponentUpdate(是否更新) 
            性能优化 PureComponent
        componentDidUpdate
    3、卸载 componentDidUnmount
        销毁定时器
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

13.2 更新原理

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

14、ref

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

14.1 React.createref()

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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

14.2 回调函数写法

		ref={(c)=>{this.input1=c}}
      1、c 实际上为当前DOM实例
      2、将 c 挂载到this上
      3、并取名为 input1
      4、这样便可以通过this.input1 拿到该 DOM
  • 1
  • 2
  • 3
  • 4
  • 5
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>
				)
			}
		}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

15、context(类似于provide和inject)

    适用于跨级组件通信
    1、声明公用的context组件
    2、传递方:provider
    3、接收方:
      (1) consumer组件 + 作用域插槽
      (2) 静态属性contextType + this.context
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

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): 参数为函数, 接收原本的状态值, 返回新的状态值, 内部用其覆盖原来的状态值
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

16.2 useEffect

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

16.3 useMemo

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

16.4 useCallback

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

16.5 useRef

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

16.6 useContext

    1、创建context方式不变
      const Context = React.createContext()
    2、【使用方】useContext 直接接收值
      let value = useContext(Context)
  • 1
  • 2
  • 3
  • 4

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

    【用途】提取公用逻辑,实现复用
  • 1

18、组件性能优化

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

19、组件库

    Ant Design
      1、Button
      2、Table 插槽
      3、定制主题 ConfigProvider
  • 1
  • 2
  • 3
  • 4
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/727868
推荐阅读
相关标签
  

闽ICP备14008679号