• React(10)-组件通信(important)


    目录

    React单项数据流

    1.组件数据源:state/props

    【面试】对state和props的理解?

    props:

    state:

    UI视图层:(模板+页面=UI视图层)

    2.单向数据流演示

    单向数据流

    React瀑布流

    组件通信( important! )

    10种React组件之间通信的方法

    组件通信-检查Typechecking with PropTypes

    一个组件实现任务列表

    多个组件实现任务列表

    多组件实现流程:

    多组件开发流程:

    拆分组件思维逻辑:

    0.组件分析

    1.数据位置(注意!!)

    2.行为位置

    3.子组件修改父组件里面的状态

    4.组件定义

    5.函数组件

    6.类组件


    React单项数据流

    1.组件数据源:state/props

    【面试】对state和props的理解?

    state/props是组件的数据源

    props:

    props:是组件对外的接口,组件和组件之间形成组件树,组件树之间数据的传递都依靠的是props.

    上层组件的props:具体指数据和方法(props可以传递数据和方法),通过上层组件传递给下一层组件

    state:

    state:是组件对内的接口只能对内直接使用,对外使用需要通过属性的方式

    state私有的:每个组件都在维护自己的私有状态。

    UI视图层:(模板+页面=UI视图层)

    视图层变化依据props和state

    props或自身state变化=>调用render=>React机制产生DOM重新计算(源码)=>重新渲染=>页面变化

    2.单向数据流演示

    单向数据流

    底层操作顶层的行为,基于props由父传子传递子组件不能直接改变父类的属性子类通过父类传递的属性绑定行为可以改变父类的状态

    优点:使数据可控,不混乱

    App(根组件)=>C1=>C2=>C3

    function C3(props){

            console.log("C3",props)

            return(

                   

                           

    C3 Component

                           

                    

            )

    }

    function C2(props){

            console.log("C2",props)

            return(

                   

                           

    C2 Component

                            //解包,传递所有数据

                            {...props}/>

                    

            )

    }

    function C1(props){

            console.log("C1",props)

            return(

                   

                           

    C1 Component

                            //解包,传递所有数据

                            {...props}/>

                    

            )

    }

    class App extends React.Component{

            //数据

            state={name:"jack",age:18,single:false}

            //行为方法

            handleClick=()=>{

                    this.setState({single:true})

            }

            render(){

                    return(

                           

                                   

    App组件

                                   

    single:{this.state.single?"不单身":"单身"}

                                    //适用于传递部分数据

                                    {/* */}

                                    //解包,适用于传递所有数据

                                    //state对内接口,传递数据和行为方法

                                    {...this.state} click={this.handleClick}>

                                     //添加行为后,传递行为信息

                           

                    )

            }

    }

    ReactDOM.render(,document.getElementById("app"))

    React瀑布流

     多个组件形成组件树(props+state)

    组件通信( important! )

    10种React组件之间通信的方法https://zhuanlan.zhihu.com/p/326254966

    父传子:数据流

    子传父:回调函数,context,redux公共状态(把状态抽离单独放置)

    组件通信-检查Typechecking with PropTypes

    官网:

    使用 PropTypes 进行类型检查 – Reacthttps://zh-hans.reactjs.org/docs/typechecking-with-proptypes.html#gatsby-focus-wrapper

    React拥有内置的类型检测机制,为组件的props运行类型检测。

    PropTypes定义为组件类自身的属性,用以定义prop的类型。在开发模式下,当提供一个不合法的值作为prop时,控制台会出现警告;在产品模式下,为了性能考虑应忽略propTypes

    引入库:

    class Student extends React.Component{

            //和Student.defaultProps效果一样,只不过是不同语法糖

            //react自带的,做安检用

            static defaultProps={

                    single:"保密'

            }

            //引用检查库中带的方法

            static propTypes = {

                    name:PropTypes.string.isRequired,

                    age:ProTypes.number.isRequired

            }

            static 

            constructor(props){

                    super(props)

                    console.log(props)

            }

            render(){

                    console.log(this.props)

                    let {name,age} = this.pops

                    return(

                           

                                   

      name:{name}

                                   

      age:{age}

                                   

      single:{single}

                            

                    )

            }

    }

    //验证:constructor打印props时,已经有single了

    说明defaultProps发生在costructor构造函数执行之前

    Student.defaultProps={

            single:"保密'

    }

    {/*

    //检查

    Student.propTypes= {

            name:ProtoTypes.string.isRequired

            age:ProtoTypes.number.isRequired

    }

    */}

    const student ={

            name:"jack",

            age:18

    }

    ReactDOM.render({...student}/>,document.getElementById("app"))

    一个组件实现任务列表

     

    页面显示:

                    

                           

    Today Tasks:0

                           

                           

                                   

                                   

                            

                           

                           

                                   

                                             

    • 0--eatting--2022/09/03 
    •                                        

    • 0--eatting--2022/09/03 
    •                                        

    • 0--eatting--2022/09/03 
    •                                

                            

                    

    页面重构:

    受控组件写法

    class App extends React.Component{

            //数据

            state = {

                    tasks:[],

                    task:"",

                    date:new Date().toLocalDateString()

            }

            //行为

            (1)任务同步:input输入框同步到task

            handleChange = (e) => {

                    console.log(e.target) 

                     this.setState({

                            task:e.target.value //替换task默认值

                    },()=>{

                            console.log("task2",this.state.task)

                     //解决"state1"打印存在异步问题,添加新的箭头函数作为参数

                    })

                    console.log("task1",this.state.task)

                    //接收不到正确的输入框内内容

                    原因:setState在合成事件中是异步的,打印的时候还是取的上一次内容

            }

            (2)添加任务:task放到tasks中

            handleAddTask = () =>{

                    const {task,tasks} = this.state,

                    //task为空字符串的时候就不用在添加了,return跳出

                    if(!task){

                            return 

                    }

                    tasks.unshift(task) //将task添加到tasks的前面

                    注:unshift返回新数组长度,不是新数组,直接改变原数组

                    this.setState({

                            tasks:tasks

                            //添加完成后,清空input输入框中内容,使其为空

                            task:""

                            date:new Date().toLocalDateString()

                    },()=>{

                            console.log(this.state)

                    })

            }

            (3)删除任务:tasks删除某个task

            handleDelete(index){

                    const {tasks} = this.state //已经通过bind绑定了this,解决了this指向问题

                    console.log(index)

                     //删除操作,原数组发生变化

                    tasks.splice(index,1)

                    this.setState({

                            tasks 

                    })

            }

            render(){

                    

    Today Tasks:{this.state.tasks.length}

                           

            value={this.state.task} //双向绑定

                    onChange={this.handleChange}/>

            

                           

            

      { this.state.tasks.map((item,index)=>{return(

                      

    • key={index}>

                              {index+1}--{task}--{this.state.date}

                               

                      

    •  ) }) }

              

            

            }

    }

    ReactDOM.render(,document.getElementById("app"))

    多个组件实现任务列表

    多组件实现流程:

    原型=>保真图=>静态页面(html css js)=>react component大组件(视图/行为/数据)=>拆分小组件

    多组件开发流程:

    1. 定义各自组件
    2. 定义视图 和 组件组合
    3. 定义数据
    4. 定义行为
    5. 组件通信(props=>数据 行为:事件绑定)

    拆分组件思维逻辑:

    0.组件分析

    App组件

            --添加组件 AddTask

            --列表组件 TaskList

                    --列表项组件 TaskItem

    1.数据位置(注意!!)

    数据是某个组件自己需要,直接定义到自己的组件里面

    数据是一些组件共同需要,定义在父组件里面,方便调用

    2.行为位置

    视图=>触发行为=>改变数据=>重新渲染

    数据在哪个组件里面,那么修改该数据的行为就在哪个组件里面,方便行为可以直接调用this.setState修改数据

    3.子组件修改父组件里面的状态

    例如:AddTask / TaskList都需要修改父组件

    父组件 - props(methods) - 子组件 [button - 行为 - 父组件的method]

    4.组件定义

    函数组件和类组件的选择,依据是否有状态

    有=>定义为类组件

    没有=>定义为函数组件

    5.函数组件

    函数组件性能更高,函数组件具有纯函数的特点,函数组件主要作用就是渲染页面,不对数据进行操作,又称之为UI组件。

    函数组件匈奴呢个更高,优先函数组件。

    6.类组件

    类组件涉及数据操作比较复杂,所以称之为复杂组件或容器组件

    class App extends React.Component{

            state = {

                    tasks : []

            }

            //添加任务:props传给AddTask

            addTask = (task) =>{

                    const {task} = this.state

                    if(!task){

                            return

                    }

                    let taskNew = {task:task,date:new Date().toLocaleTimeString()}

                    tasks.unshift(taskNew )

                    this.setState({

                            task:task

                    })

            }

            //删除任务:props传给TaskItem

            deleteTask=(index)=>{

                    const {tasks} = this.state

                    tasks.splice(index,1)

                    this.setState({

                            tasks

                    })

            }

            render(){

                    return(

                   

                           

    Today Tasks:{this.state.tasks.length}

                           

                           

                   

                    )

            }

    }

    //添加任务

    class AddTask extends React.Component{

            state = {task:""}

            //任务同步

            handleChange=(e)=>{

                    this.setState({

                            task:e.target.value

                    })

            }

            //子组件调用父组件方法添加

            handleAddTask=()=>{

                    const {task} = this.state

                    if(!task){

                            return 

                    }

                    this.props.addTask(task)

                    //添加完成之后清除input输入框

                    this.setState({

                            task:""

                    })

            }

            render(){

                    return(

                   

                           

                           

                   

                    )

            }

    }

    //任务列表

    //没有自己的状态,不需要维护自己的数据,定义为函数组件

    function TaskList(props){

    //函数组件和类组件传参不同,函数组件是通过props作为参数传递,类组件是通过this.props传递

            return(

                    

                              {

                                      props.tasks.map((item,index)=>{

      return key={index}  key添加在距离数据源最近的地方

              index={index} task={item.task} date={item.date} daleteTask={props.daleteTask}>

                                      })

                              }

                             

                      

            )

    }

    function TaskItem(props){

            function handleDelete(){

                    props.deleteTask(props.index)

            }

            //调用父组件删除

            return(

  • key={index}>

            {props.index+1}--{props.task}--{props.date}

             

  •         )

    }

  • 相关阅读:
    搞脑筋的日历积木
    【小程序】小程序开发中背景及图片图片失效处理……
    使用Docker搭建分布式文件存储系统MinIO
    爬虫 — JsonPath 和 CSV 文件读写
    redis的简介和常用
    【数学建模】历年全国大学生数学建模竞赛题目+定位分析
    计算机毕业设计springboot+vue+elementUI 广场舞团高校舞蹈社团管理系统
    Zabbix (四) --------- Zabbix 集成 Grafana
    [Java]枚举类
    你看不上的自助餐,正在下沉市场迎来“第二春”
  • 原文地址:https://blog.csdn.net/m0_65912225/article/details/126659104