React-4 组件知识

目录

一、状态 :state

1、组件的状态

2、组件中的数据

3、在类中定义state(只能写这个名字)对象

4、使用setState要注意:

二、属性:props(只读)

1、state是内部属性,props是为了更好地实现复用性,从外部接收数据

2、某组件

3、MyNav.js

4、函数式组件对于属性的应用会更简单一些,直接通过形参可以获得

三、属性及状态总结

1、属性是父组件对子组件的数据传输与操作

2、状态是组件自己内部的数据

四、表单

1、受控表单元素

2、非受控表单元素

五、通信

1、父传子:属性值

2、子传父:回调函数

3、在父组件中对子组件进行ref标记,可以获取到子组件的引用

4、中间人模式:由父组件充当中间人,利用子传父+父传子模式完成

5、发布订阅模式

6、context状态树传参(官方提供)

7、Redux:这个后面会讲到

六、插槽

1、默认形式

2、按顺序插入

3、作用

七、生命周期(钩子函数)

1、初始化阶段

2、运行中阶段

3、销毁阶段

八、新生命周期(推荐)

1、老钩子问题

2、static getDeriveStateFromProps(nextProps,nextState)


一、状态 :state

1、组件的状态

(1)有状态组件:设置了state的组件称之为有状态组件。   eg:类组件

(2)无状态组件:没有设置state的组件称之为无状态组件   eg:函数组件

2、组件中的数据

class  A  extends  Component{
    state = {key:value}
}
class  A  extends  Component{
   constructor(){
      super();
      this.state = {
         key:value
      }
   }
}

3、在类中定义state(只能写这个名字)对象

state = {key:value}

注意:<1>不要直接修改state(状态)

//错误写法
this.state.comment = 'ok'

          <2>要使用 this.setState()来更新state 

//正确写法
//this.setState({key:value})
this.setState({comment: 'ok'});

4、使用setState要注意:

(1)在同步逻辑中,异步更新状态与真实dom

import React, { Component } from 'react' 
export default class App extends Component {
    state={
        count:1
    }
    render() {
        return (
            <div>
                {this.state.count}
                <button onClick={this.handleClick}>同步逻辑</button>
                <button onClick={this.handleClick2}>异步逻辑</button>
            </div>
        )
    }

    handleClick=()=>{
        this.setState({
            count:this.state.count+1
        })
        console.log(this.state.count);
        this.setState({
            count:this.state.count+1
        })
        console.log(this.state.count);
 
        this.setState({
            count:this.state.count+1
        })
        console.log(this.state.count);
 
    }
}

(2)在异步逻辑中,同步更新状态与真实dom

import React, { Component } from 'react'
export default class App extends Component {
    state={
        count:1
    }
    render() {
        return (
            <div>
                {this.state.count}
                <button onClick={this.handleClick}>同步逻辑</button>
                <button onClick={this.handleClick2}>异步逻辑</button>
 
            </div>
        )
    }

    handleClick2=()=>{
        setTimeout(()=>{
            this.setState({
                count:this.state.count+1
            })
            console.log(this.state.count);
            this.setState({
                count:this.state.count+1
            })
            console.log(this.state.count);
    
            this.setState({
                count:this.state.count+1
            })
            console.log(this.state.count);
        },0)
    }
}

(3)接受第二个参数,是个回调函数,在这里状态与dom更新完毕

    handleClick = ()=>{
        this.setState({
            count:this.state.count+1
        },()=>{
            console.log(this.state.count)
        })
 
        this.setState({
            count:this.state.count+1
        },()=>{
            console.log(this.state.count)
        })
 
        this.setState({
            count:this.state.count+1
        },()=>{
            console.log(this.state.count)
            // 状态和真实dom已经更新完毕
        })
    }

二、属性:props(只读)

1、state是内部属性,props是为了更好地实现复用性,从外部接收数据

//父组件
<MyNav title={this.title} />
 
 
//MyNav.js组件
render(){
 return (
  <div>
    <p>{this.props.title}<p/>
  </div>
 )
}

2、某组件

{/*属性*/}
<MyNav title={this.title} leftBtn={isShowLeft}/>

3、MyNav.js

render(){
 let {title,leftBtn}=this.props;
 return (
 <div>
    {leftBtn && <button>left</button>}
   <p>{title}</p>
   <button>right</button>
    <img{...obj}/>
  </div>
 )
}

(1)属性验证

import myprop from 'prop-types'
static propTypes={
   title:myprop.string,
   letBtn:myprop.bool
}

(2)默认属性

//默认属性

static defaultProps={
   title:'首页'
}

4、函数式组件对于属性的应用会更简单一些,直接通过形参可以获得

三、属性及状态总结

1、属性是父组件对子组件的数据传输与操作

2、状态是组件自己内部的数据

四、表单

1、受控表单元素

(1)由React控制

(2)value绑定state中的值

(3)实现表单元素的change事件

(4)优化:可以使用name属性,统一完成change事件

(5)注意:选择框与其他表单元素获取值的方式不一样

class App extends React.Component {
    state = {
        txt: '',
        content: '',
        city: 'bj',
        isChecked: false
    }

    handleChange = e => {
        this.setState({
            txt: e.target.value
        })
    }

    // 处理富文本框的变化
    handleContent = e => {
        this.setState({
            content: e.target.value
        })
    }

    // 处理下拉框的变化
    handleCity = e => {
        this.setState({
            city: e.target.value
        })
    }

    // 处理复选框的变化
    handleChecked = e => {
        this.setState({
            isChecked: e.target.checked
        })
    }

    render() {
        return (
            <div>
                {/* 文本框 */}
                <input type="text" value={this.state.txt} onChange={this.handleChange} />
                <br/>

                {/* 富文本框 */}
                <textarea value={this.state.content} onChange={this.handleContent}></textarea>
                <br/>

                {/* 下拉框 */}
                <select value={this.state.city} onChange={this.handleCity}>
                    <option value="sh">上海</option>
                    <option value="bj">北京</option>
                    <option value="gz">广州</option>
                </select>
                <br/>

                {/* 复选框 */}
                <input type="checkbox" checked={this.state.isChecked} onChange={this.handleChecked} />
            </div>
        )
    }
}

2、非受控表单元素

(1)由DOM控制

(2)在constructor中React.createRef()

class App extends React.Component {
  constructor() {
    super()

    // 1.创建ref
    this.txtRef = React.createRef()
  }

  // 获取文本框的值
  getTxt = () => {
      // 3. 通过ref对象来获得表单元素的值
    console.log('文本框值为:', this.txtRef.current.value);
  }

  render() {
    return (
      <div>
        // 2.将创建好的 ref 对象添加到表单元素中
        <input type="text" ref={this.txtRef} />
        <button onClick={this.getTxt}>获取文本框的值</button>
      </div>
    )
  }
}

五、通信

1、父传子:属性值

(1)父组件提供传递的数据

(2)给子组件标签添加属性,值为state中的数据

(3)子组件中通过props接收父组件中传过来的数据

// 子组件
export class tab extends Component {
  render() {
    return (
      <div>
       {this.props.msg}
      </div>
    )
  }
}
 
// 父组件
export class exer extends Component {
  state = {
    mesg: 'msg',
  }
  render() {
    return (
      <div>
       <tab msg={this.state.mesg} />
      </div>
    )
  }
}

2、子传父:回调函数

(1)父组件提供一个回调函数,用于接收数据

(2)将函数作为属性的值,传给子组件

(3)子组件通过props调用回调函数

(4)将子组件中的数据作为参数传给回调函数

// 子组件
export class tab extends Component {
 
  render() {
    return (
      <div>
       <p
       onClick={() =>{
          this.props.changeMes("返回数据")
        }
       }
       >tab</p>
      </div>
    )
  }
}
 
// 父组件
export class exer extends Component {
  state = {
    mesg: 'msg',
  }
  changemes = (newmsg) => {
    this.state({
      meg: newmsg
    })
  }
  render() {
    return (
      <div>
       <tab changeMes={this.changemes} />
      </div>
    )
  }
}

3、在父组件中对子组件进行ref标记,可以获取到子组件的引用

4、中间人模式:由父组件充当中间人,利用子传父+父传子模式完成

(1)公共父组件提供共享状态,提供共享状态的方法

(2)要接收数据状态的子组件通过 props 接收数据

(3)要传递数据状态的子组件通过props接收方法,调用方法传递数据

5、发布订阅模式

let  bus = {
   list:[],   //存放订阅者
   //订阅者
   subscrible(cb){
      this.list.push(cb);
   },
   //发布者
   publish(text){
      this.list.forEach(cb => cb &&  cb(text))
   }
}

6、context状态树传参(官方提供)

(1)父组件

<GlobalContext.Provider   value = { {a:1,b:2} }>
      <Child1></Child1>
      <Child2></Child2>
</GlobalContext.Provider>

(2)子组件

<GlobalContext.Consumer>
   {
      value =>{
         return  (
            <div>子组件{value}</div>
         )
      }
   }
</GlobalContext.Consumer>

注意:value是固定的关键词

7、Redux:这个后面会讲到

六、插槽

1、默认形式

(1)父组件

<Child>
    <p>插入任意内容<p/>
</Child>

(2)子组件

return (
    <div>
        <p>子组件内部标签</p>
        {/* 以下内容是插槽内容,外部代码在此进行替代 */}
        {this.props.children}
        {/* 固定写法 */}
    </div>
)

2、按顺序插入

父组件:
<Child>
    <p>西游记<p/>
    <p>红楼梦<p/>
    <p>水浒传<p/>
</Child>

子组件Child:
return (
    <div>
        {this.props.children[0]}
        {this.props.children[1]}
        {this.props.children[2]}
    </div>
)

3、作用

(1)提高代码的复用性

(2)一定程度上减少父子通信

七、生命周期(钩子函数)

1、初始化阶段

(1)componentWillMount

     <1>组件即将挂载,render之前最后一次修改state的机会

     <2>常用于:state的初始化

     <3>注意:如果有警告,可使用UNSAFE_componentWillMount

(2)render(渲染):只能访问props与state,不能修改state及进行dom输出

(3)componentDidMount

     <1>成功执行完毕render并完成dom节点的渲染,可以对dom修改

     <2>常用于:axios请求,订阅函数调用,计时器,dom操作

2、运行中阶段

(1)componentWillReceiveProps(nextProps)

     <1>父组件修改属性触发

     <2>最先获取父组件传来的属性,可以在这里进行axios请求或者其他逻辑处理

     <3>注意:如果有警告,可使用UNSAFE_componentWillReceiveProps

(2)shouldComponentUpdate(nextProps,nextState)

     <1>返回false,会阻止render的调用

     <2>参数是被修改之后的新的属性及状态

(3)componentWillUpdate

     <1>组件将要更新,不能修改该属性及状态

     <2>注意:如果有警告,可使用UNSAFE_componentWillUpdate

(4)render(渲染):只能访问props与state,不能修改state及进行dom输出

(5)componentDidUpdate(preProps,preState)

     <1>可以修改dom

     <2>参数是被修改之前的属性及状态

3、销毁阶段

(1)componentWillUnmount

(2)在删除组件前进行清理工作

注意:写在前边:只有类组件(函数组件需要hooks支持)

八、新生命周期(推荐)

1、老钩子问题

componentWillmount会重复触发多少次,如果绑定事件无法解绑

2、static getDeriveStateFromProps(nextProps,nextState)

(1)将属性转为状态

(2)挂载之前于更新会执行

(3)返回一个状态对象

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值