IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> React 补充 -> 正文阅读

[JavaScript知识库]React 补充

setState 更新状态的其他写法

我们正常使用时很简单的用第一种方法:

?this.setState({

? ? ? num:this.state.num + 1

? ? }

其实后面还可以跟上第二个参数(函数)?在render之后才执行

? ? this.setState({

? ? ? num:this.state.num + 1

? ? },() =>{

? ? ? console.log(this.state.num);

? ? })

还可以直接写成 函数形式的

this.setState( (state,props) => ({num:props.add * state.num}))?

总结:

? ? 1.对象式的setState是函数式的setState的简写方式(语法糖)

? ? 2.使用原则:

? ? ? ? (1).如果新状态不依赖于原状态 ===> 使用对象方式

? ? ? ? (2).如果新状态依赖于原状态 ===> 使用函数方式

? ? ? ? (3).如果需要在setState()执行后获取最新的状态数据,要在第二个callback函数中读取

路由懒加载?

路由激活前再加载? 引入的时候写法改变下 其他的一切照旧

正常:import About from './About'

懒加载:const About = lazy(()=> import('./About'))

还可以自定义Loading界面

	//2.通过<Suspense>指定在加载得到路由打包文件前显示一个自定义loading界面
	<Suspense fallback={<h1>loading.....</h1>}>
        <Switch>
            <Route path="/xxx" component={Xxxx}/>
            <Redirect to="/login"/>
        </Switch>
    </Suspense>

Fragment

<Fragment>

<div></div>

<div></div>

<Fragment>

可以不用必须有一个真实的DOM根标签了

Context

一种组件间通信方式, 常用于【祖组件】与【后代组件】间通信

首先引入

// 创建Context对象

const MyContext = React.createContext()

// 解构出想用的api ?provider提供者统一提供 ?consumer-用于函数类后代组件

const {Provider,Consumer} = MyContext

渲染子组件时外部要包裹

? ? ? ? <Provider value={{username,age}}>

? ? ? ? ? ? <子组件></子组件>

? ? ? ? </Provider>

?类式组件使用?

静态声明:? static contextType = MyContext

解构引用:? const {username,age} = this.context

?函数组件使用

? ? ? ?<Consumer>// value就是context中的value数据

? ? ? ? ?{value => `${value.username}---${value.age}`}

? ? ? ?</Consumer>

?完整代码:

import React, { Component } from 'react'
import './index.css'

// Context 用于隔代通讯  一般不用

// 创建Context对象
const MyContext = React.createContext()
// 解构出想用的api  provider提供者统一提供  consumer-用于函数类后代组件 
const {Provider,Consumer} = MyContext

export default class Context extends Component {
  state = {username:'tony',age:24}
  render() {
    const {username,age} = this.state
    return (
      <div className='parent'>
        <h3>我是一代目</h3>
        <h4>本座的名讳是{username}</h4>
        <Provider value={{username,age}}>
            <D></D>
        </Provider>
      </div>
    )
  }
}

class D extends Component{
  render(){
    return(
          <div className='child'>
      <h3>我是二代目</h3>
      <E></E>
    </div>
    )

  }
}

class E extends Component{
  // 类式 后代组件 生命静态属性接收
  static contextType = MyContext
  render(){
    const {username,age} = this.context
    return(
    <div className='grand'>
      <h3>我是三代目</h3>
      <h4>直接会用初代目的技能{username}--{age}</h4>
      <F></F>
    </div>
    )
  }
}

function F(){
  return(
    <div className='sun'>
       <h3>我是四代(函数组件)</h3>
       <Consumer>
         {value => `${value.username}---${value.age}`}
       </Consumer>
    </div>
  )
}

?PureComponent

用来解决组件? 没有意义的render问题?

> 1. 只要执行setState(),即使不改变状态数据, 组件也会重新render()

> 2. 只当前组件重新render(), 就会自动重新render子组件 ==> 效率低

有用的render:只有当组件的state或props数据发生改变时才重新render()

原因:生命周期中的shouldComponentUpdate()总是返回true

? 办法1:

? ? 重写shouldComponentUpdate()方法

? ? 比较新旧state或props数据, 如果有变化才返回true, 如果没有返回false

? 办法2: ?

? ? 使用PureComponent

? ? PureComponent重写了shouldComponentUpdate(), 只有state或props数据有变化才返回true

? ? 注意:

? ? ? 只是进行state和props数据的浅比较, 如果只是数据对象内部数据变了, 返回false ?

? ? ? 不要直接修改state数据, 而是要产生新数据

? 项目中一般使用PureComponent来优化

完整代码:

import React, { PureComponent } from 'react'
import './index.css'

export default class Parent extends PureComponent {
  state = {carName:'AMG s65',people:['小曲','小魏','小张']}

  newCar = () =>{
    this.setState({
      carName:'M5'
    })
  }

  // shouldComponentUpdate(nextProps,nextState){
	// 	// console.log(this.props,this.state); //目前的props和state
	// 	// console.log(nextProps,nextState); //接下要变化的目标props,目标state
	// 	return !(this.state.carName === nextState.carName)
	// } 

  addp = () =>{
    const {people} = this.state
    people.unshift('老吴')
    this.setState({people})
  }

    addb = () =>{
    const {people} = this.state
    this.setState({people:['老吴',...people]})
  }

  render() {
    console.log('P的render')
    return (
      <div className='parent'>
          <h3>我是parent组件</h3>
          {this.state.carName}
          <button onClick={this.newCar}>点击换车</button>
          <C carName={this.state.carName}></C>
          <div>
            <button onClick={this.addp}>点击增加人数(会认为没变化)</button>
            <button onClick={this.addb}>正确增加老吴</button>
            <br />
            {JSON.stringify(this.state.people)}
          </div>
      </div>
    )
  }
}


class C extends PureComponent {
  
	// shouldComponentUpdate(nextProps,nextState){
	// 	console.log(this.props,this.state); //目前的props和state
	// 	console.log(nextProps,nextState); //接下要变化的目标props,目标state
	// 	return !(this.props.carName === nextProps.carName)
	// } 

  render(){
    console.log('C的render')
    return (
      <div className='child'>
          <h3>我是child组件</h3>
          <span>我接到的车是:{this.props.carName}</span>
          <p>
            为了更高效  有时候子组件数据不需要更新 而触发render  父组件用了 setState 但数据并没有发生变化
            <br /> 一直搞不懂为什么 render 都是执行两次
            <br />解决方式 1 使用shouldComponentUpdate 判断数据变化 返回布尔值 
            <br /> 解决方式2 直接使用 PureComponent 自动比较  但注意写法  对象的地址一样 是不会改变的
          </p>
      </div>
    )
  }
}

render props

? Vue中:

? ? 使用slot技术, 也就是通过组件标签体传入结构 ?<AA><BB/></AA>

? React中:

? ? 使用children props: 通过组件标签体传入结构

? ? 使用render props: 通过组件标签属性传入结构, 一般用render函数属性

### children props

? <A>

? ? <B>xxxx</B>

? </A>

? {this.props.children}

? 问题: 如果B组件需要A组件内的数据, ==> 做不到

### render props

? <A render={(data) => <C data={data}></C>}></A>

? A组件: {this.props.render(内部state数据)}

? C组件: 读取A组件传入的数据显示 {this.props.data}

完整代码:

import React, { PureComponent } from 'react'
import './index.css'

export default class Parent extends PureComponent {
  state = {carName:'AMG s65',people:['小曲','小魏','小张']}

  newCar = () =>{
    this.setState({
      carName:'M5'
    })
  }

  addp = () =>{
    const {people} = this.state
    people.unshift('老吴')
    this.setState({people})
  }

    addb = () =>{
    const {people} = this.state
    this.setState({people:['老吴',...people]})
  }

  render() {
    console.log('P的render')
    return (
      <div className='parent'>
          <h3>我是parent组件</h3>
          {this.state.carName}
          <button onClick={this.newCar}>点击换车</button>
          
          <div>
            <button onClick={this.addp}>点击增加人数(会认为没变化)</button>
            <button onClick={this.addb}>正确增加老吴</button>
            <br />
            {JSON.stringify(this.state.people)}
          </div>


{/* C内部直接传入D C内部也预留好插槽 */}
          <C carName={this.state.carName} render={ccc => <D ccc={ccc}></D>}></C>
      </div>
    )
  }
}


class C extends PureComponent {
  


  render(){
    const ccc = 123
   // console.log('C的render')
    return (
      <div className='child'>
          <h3>我是child组件</h3>
          <span>我接到的车是:{this.props.carName}</span>
          <p>以下是预留的插槽</p>
          {this.props.render(ccc)}
      </div>
    )
  }
}

class D extends PureComponent {
  
  render(){
    return (
      <div style={{background:'#f35'}}>
          <h3>我是D组件</h3>
          {this.props.ccc}
      </div>
    )
  }
}

?错误边界

错误边界:用来捕获后代组件错误,渲染出备用页面 不会因为某个组件的错误 导致全部页面渲染不出来

#### 特点:

只能捕获后代组件生命周期产生的错误,不能捕获自己组件产生的错误和其他组件在合成事件、定时器中产生的错误

import React, { Component } from 'react'
import Child from './Child'

export default class Parent extends Component {
  state = {
    hasError:'' // 用于标识子组件是否产生错误
  }

//当Parent的子组件出现报错时候,会触发getDerivedStateFromError调用,并携带错误信息
static getDerivedStateFromError(error){
  console.log('@@@',error)
  return {hasError : error}
}

componentDidCatch(){
  console.log('此处统计错误,反馈给服务器,通知编码人员进行分析解决')
}

  render() {
    return (
      <div>
        <h2>我是Parent组件</h2>
        {this.state.hasError ? <h2>子组件显示不了</h2>: <Child></Child>}
      </div>
    )
  }
}
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-21 00:19:29  更:2022-09-21 00:20:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 10:22:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码