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

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

10.1 基本使用

    1、传递方式与函数组件一致
    2、接收时通过 this.props.mes 获取
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 库
// 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 具名插槽

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
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、父组件拿到数据
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()

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
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
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

    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
  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值