react 组件传值 事件 状态机 改变this指向

props

正向传值

props能修改吗?

props是只读的 不能修改

语法:

props函数组件

语法 :

只需要在函数组件中添加一个props的形参 即可使用props

子组件接收

// 子组件需要把props当成形参传入
let Zi=(props)=>{
    let {text,num}=props
​
    return(
        <div>
            zizizziziziziz---{text}--{num}
        </div>
    )
}
export default Zi

父组件传递

import Fz from "./funpropszi.jsx"
let Fu=()=>{
    let obj={text:"text数据",num:"num数据"}
    return(
        <div>
            fufufufuffufufu
            {/* 传递参数可是用扩展运算符 */}
            <Fz {...obj}/>
        </div>
    )
}
export default Fu

props类组件

this.props.xxx

1.子组件配置props

import React, { Component } from 'react'
​
export default class propszi extends Component {
    render() {
        return (
            <div>
                zizizzizizizizzz---{this.props.text}
                <br />
                {this.props.num}
            </div>
        )
    }
}

2.父组件传值

import React, { Component } from 'react'
​
import Pz from "./propszi.jsx"
export default class propsfu extends Component {
    render() {
        return (
            <div>
                fuffufufufufuffu
                {/* 父组件传值 */}
                <Pz text="我是父组件的text" num="我是父组件的num"/>
            </div>
        )
    }
}

上面的写法太low了 改编一下(以后就这样写)

子组件接收数据的时候 使用解构赋值的方式取出this。props的数据

import React, { Component } from 'react'
​
export default class propszi extends Component {
    render() {
        // 由于this.props是一个对象  为了让代码看起来更加简洁  所以我们
        // 使用解构赋值的方式  把props中的数据快速取出来
        let {text,num}=this.props
        return (
            <div>
             zizizizizizizziiz---{text}---{num}
            </div>
        )
    }
}

父组件传递

import React, { Component } from 'react'
​
import Pz from "./propszi.jsx"
export default class propsfu extends Component {
    render() {
        let obj={text:"我是父组件的text",num:"我是父组件的num"}
        return (
            <div>
                fuffufufufufuffu
                {/* 父组件传值  使用扩展运算符可以简化我们在父组件给
                    子组件传递数据时候的复杂度
                */}
                <Pz {...obj} />
            </div>
        )
    }
}
​

props 验证

rccp

注意:

自 React v15.5 起,React.PropTypes 已移入另一个包中。请使用 [prop-types 库](prop-types - npm) 代替。

子组件验证,错误则会提示

// import React, { Component } from 'react'
​
// export default class propszi extends Component {
//     render() {
//         // 由于this.props是一个对象  为了让代码看起来更加简洁  所以我们
//         // 使用解构赋值的方式  把props中的数据快速取出来
//         let {text,num}=this.props
//         return (
//             <div>
//              zizizizizizizziiz---{text}---{num}
//             </div>
//         )
//     }
// }
​
​
​
import React, { Component } from 'react'
// 包要引
import PropTypes from 'prop-types'
​
export default class propszi extends Component {
    // 使用PropTypes来进行props的验证
    static propTypes = {
        text: PropTypes.string,
        num:PropTypes.number
    }
​
    render() {
        let {text,num}=this.props
        return (
            <div>
                 zizizizizizizziiz---{text}---{num}
            </div>
        )
    }
}

状态机state

状态==数据

状态机===数据机制

数据等同于状态 状态改变页面也会改变

函数组件可以使用状态吗?

函数组件默认情况下不能使用状态 后面会学到高阶语法HOOK才能使用

语法

状态创建

import React, { Component } from 'react'
​
export default class statedemo extends Component {
    // 创建状态  需要写在constructor中
    // 在es6中  子类写不写constructor 在实例的过程中 都会给补上他
    // 但是如果我们写了  那么必须写super()
    // super就是调用父类构造方法  只有写了子类才有自己的this  
    // 如果只写了constructor不写super()那么以后使用this的时候指向都是错误的
    constructor(){
        super()
​
        // 创建状态
        this.state={
            text:"字符串",
            num:18,
            arr:[111,2222,33333],
            obj:{name:"xxixi"}
        }
    }
​
    render() {
        return (
            <div>
                <h1>状态的使用</h1>
            </div>
        )
    }
}
​

读取状态

在想使用的地方使用 this.state.xxx

import React, { Component } from 'react'
​
export default class statedemo extends Component {
    // 创建状态  需要写在constructor中
    // 在es6中  子类写不写constructor 在实例的过程中 都会给补上他
    // 但是如果我们写了  那么必须写super()
    // super就是调用父类构造方法  只有写了子类才有自己的this  
    // 如果只写了constructor不写super()那么以后使用this的时候指向都是错误的
    constructor(){
        super()
​
        // 创建状态
        this.state={
            text:"字符串",
            num:18,
            arr:[111,2222,33333],
            obj:{name:"xxixi"}
        }
    }
​
    render() {
        return (
            <div>
                <h1>状态的使用</h1>
                {/* 使用状态 */}
                <em>{this.state.num}-----{this.state.text}---{this.state.arr[1]}</em>
            </div>
        )
    }
}

修改state

修改state不能直接使用=修改 而是要调用一个叫 setState()来进行修改

import React, { Component } from 'react'
​
export default class statedemo extends Component {
    // 创建状态  需要写在constructor中
    // 在es6中  子类写不写constructor 在实例的过程中 都会给补上他
    // 但是如果我们写了  那么必须写super()
    // super就是调用父类构造方法  只有写了子类才有自己的this  
    // 如果只写了constructor不写super()那么以后使用this的时候指向都是错误的
    constructor(){
        super()
​
        // 创建状态
        this.state={
            text:"字符串",
            num:18,
            arr:[111,2222,33333],
            obj:{name:"xxixi"}
        }
    }
​
    // 创建函数
    fun=()=>{
        // 修改state数据必须使用setState()
        this.setState({
            num:888,
            text:"我变了"
        })
    }
​
    render() {
        return (
            <div>
                <h1>状态的使用</h1>
                {/* 使用状态 */}
                <em>{this.state.num}-----{this.state.text}---{this.state.arr[1]}</em>
                <button onClick={this.fun}>点我修改</button>
            </div>
        )
    }
}
​

为什么要使用setState()来修改state

因为调用了setState之后 他会自动触发render方法重新渲染页面 从而让数据改变之后 页面也会发生改变

setState 在修改数据的时候是异步的

由于setState是一个异步的 所以他第一个参数是一个对象 用来修改数据 第二个参数是一个回调函数 是当修改完数据之后自动触发回调函数

 this.setState({
            num:888,
            text:"我变了"
        },()=>{
                 // 我就是想等数据修改之后在console中打印出来
                 console.log(this.state.num);
        })

ref

用来标识组件内部的元素 但是注意 函数组件由于没有实例所以不能使用ref

使用

1.字符串方式(已经淘汰了)

2.回调函数方式

import React, { Component } from 'react'
​
export default class refdemo extends Component {
    fun=()=>{
        console.log(this.refinput.value);
    }
    render() {
        return (
            <div>
                <h1>ref回调函数的方式</h1>
        {/* 回调函数方式绑定ref  需要在dom节点上挂载一个函数  
        函数的形参是当前dom节点    (形参)=>{随便创建一个变量=形参}*/}
​
                <input type="text" ref={(demoinput)=>{this.refinput=demoinput}}/>
                <button onClick={this.fun}>点我得到值</button>
            </div>
        )
    }
}
​

3.React.createRef() react16.3新增

import React, { Component } from 'react'
​
export default class refdemob extends Component {
    constructor(){
        super()
        // 1.创建createRef
        this.refdemo=React.createRef()
    }
​
    fun=()=>{
        // 3.使用
        console.log(this.refdemo.current.value);
    }
​
    render() {
        return (
            <div>
                <h1>createRef()</h1>
                {/* 2.绑定 */}
                <input type="text" ref={this.refdemo}/>
                <button onClick={this.fun}>点我得到值</button>
            </div>
        )
    }
}
​

事件处理机制

事件的绑定

使用小驼峰命名法来进行事件的绑定 onclick----->onClick

如果事件要调用 那么函数是不加()

函数实参传递

由于react中函数是没有()的,所以传统的实参传参方式是没有办法进行的

.bind方式进行实参的传递

onClick={this.fun.bind(this,你要传递的数据)}

使用箭头函数调用函数传参

 {/* 通过箭头函数调用函数传参 */}
<button onClick={()=>{this.funb("参数")}}>点我传参2</button>

事件的修饰

react中如果想阻止事件传播或者默认行为的话 使用同原生一样的方式

this指向修改的方法:

1.就是创建函数的时候使用箭头函数创建

2.通过.bind方式解决this

 <button onClick={this.funb.bind(this)}>bind修改this</button>

3.把函数的调用变成使用箭头函数调用

<button onClick={()=>{this.funb()}}>箭头函数调用函数</button>

4.在constructor中提前绑定

  constructor(){
        super()
        this.state={
            text:"你好"
        }
        // 提前给函数绑定this
        this.funb=this.funb.bind(this)
       
    }

条件渲染

根据我们的需要 显示或者隐藏某些内容

1.三元运算符

import React, { Component } from 'react'
​
export default class democ extends Component {
    constructor(){
        super()
        this.state={
            bool:true
        }
    }
    render() {
        return (
            <div>
                <h1>条件渲染</h1>
                {this.state.bool?<h1>吃了</h1>:<h1>没有吃</h1>}
            </div>
        )
    }
}

2.if全家桶

注意注意注意:在jsx不能写if

import React, { Component } from 'react'
​
export default class demod extends Component {
    constructor(){
        super()
        this.state={
            num:5
        }
    }
    render() {
        let com=""
        if(this.state.num==1){
            com= <h1>第1</h1>
        }else if(this.state.num==2){
            com= <h1>第2</h1>
        }else if(this.state.num==3){
            com= <h1>第3</h1>
        }else if(this.state.num==4){
            com= <h1>第4</h1>
        }else if(this.state.num==5){
            com= <h1>第5</h1>
        }
​
​
​
        return (
            <div>
                <h1>条件渲染</h1>
               
                {com}
                
            </div>
            
        )
    }
}
​

状态提升

react中状态提升就是多个组件需要反映相同的数据变化 我们可以把这个数据提升到这几个组件的父组件之上 然后在父组件中改变数据 那么通过props分发给这几个子组件即可反映相同的数据变化

扩展----多行标签-空标签

在react中 多行标签必须有一个父容器包裹 但是往往这些包裹的容器标签是没有用 在页面渲染的时候 会造成冗余代码

1.真正的空标签

import React, { Component } from 'react'
​
export default class ezia extends Component {
    render() {
        return (
            // 空标签
            <>
                <h1>我是h1</h1>
                <h1>我是h11</h1>
            </>
        )
    }
}

2.Fragment 空标签 今后会使用的比较多

import React, { Component,Fragment } from 'react'
​
export default class ezi extends Component {
    render() {
        return (
            // Fragment空标签 别忘了引用
            <Fragment>
                <h2>h222222</h2>
                <h2>h222222222222222</h2>
            </Fragment>
        )
    }
}
​

扩展----强制刷新

react 只有使用state创建的变量 在使用setState修改之后页面才会更新。

如果我就是不想在state里面写状态 也不想使用setState修改 我怎么样创建变量修改更新呢?

import React, { Component } from 'react'
​
export default class demof extends Component {
    constructor(){
        super()
​
        this.name="xixi"
    }
​
    fun=()=>{
        this.name="haha"
        console.log(this.name);
​
        // 强制触发render()渲染
        // 只要调用就会重新渲染
         this.forceUpdate()
    }
    render() {
        return (
            <div>
                <h1>页面强制刷新---{this.name}</h1>
                <button onClick={()=>{this.fun()}}>点我修改</button>
            </div>
        )
    }
}
​

组件传值

正向传值--props

详见上面内容

逆向传值

react的逆向传值 使用的也是props 只是和正向传值不同 因为正向传值传递的是数据 但是逆向传值传递的是方法

子组件

import React, { Component } from 'react'
​
export default class nizi extends Component {
    render() {
        return (
            <div>
                
                <h1>子组件</h1>
                {/* 1.子组件必须通过事件来触发逆向传值 */}
                {/* 2.子组件需要接收父组件传递过来的函数   并且使用bind进行函数实参传递 */}
                <button onClick={this.props.fun.bind(this,"子组件的数据")}>点我逆向传值</button>
            </div>
        )
    }
}
​

父组件

import React, { Component } from 'react'
import Nz from "./nizi.jsx"
export default class nifu extends Component {
    // 4.创建父组件的函数
    demo=(text)=>{
        console.log(text);
    }
    render() {
        return (
            <div>
                <h1>逆向传值</h1>
                {/* 3.子组件需要一个函数  那么父组件给他传递一个函数 */}
                <Nz fun={this.demo}/>
            </div>
        )
    }
}

同胞传值---pubsub-js

1.下载pubsub-js npm install --save pubsub-js

2.在需要传递的组件中进行数据的抛出(使用自定义事件)publish("自定义事件名","传递的参数")

import React, { Component,Fragment } from 'react'
// 1.引用pubsub-js
import PubSub from "pubsub-js"
export default class pubsubzia extends Component {
    fun=()=>{
        // 2.抛出自定事件
        PubSub.publish("pao","我是zia的数据么么哒!!!")
    }
    render() {
        return (
            <Fragment>
                <h1>zia</h1>
                <button onClick={this.fun}>点我同胞传值</button>
            </Fragment>
        )
    }
}

3.在需要数据的组件内 监听自定义事件 subscribe("你要监听的事件名",(事件,数据)=>{})

import React, { Component } from 'react'
import PubSub from "pubsub-js"
export default class pubsubzib extends Component {
​
    // 3使用生命周期自动调用subscribe()来监听自定事件
//    组件渲染之前
    componentWillMount() {
        PubSub.subscribe("pao",(a,b)=>{
            console.log(a);//监听的事件名
            console.log(b);//监听的数据
        })
    }
    // 组件渲染之后
    componentDidMount() {
        
    }
    
​
​
    render() {
        return (
            <>
                <h1>zib</h1>
            </>
        )
    }
}
​

跨组件传值

方式1 context上下文对象

方式2 redux

上一篇:060_Vue组件


下一篇:Spring8:使用注解开发