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(

                <div>

                        <h2>C3 Component</h2>

                        <button onClick={props.click}>button</button>

                </div>

        )

}

function C2(props){

        console.log("C2",props)

        return(

                <div>

                        <h2>C2 Component</h2>

                        //解包,传递所有数据

                        <C3 {...props}/>

                </div>

        )

}

function C1(props){

        console.log("C1",props)

        return(

                <div>

                        <h2>C1 Component</h2>

                        //解包,传递所有数据

                        <C2 {...props}/>

                </div>

        )

}

class App extends React.Component{

        //数据

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

        //行为方法

        handleClick=()=>{

                this.setState({single:true})

        }

        render(){

                return(

                        <div>

                                <h1>App组件</h1>

                                <h3>single:{this.state.single?"不单身":"单身"}</h3>

                                //适用于传递部分数据

                                {/* <C1 name={this.state.name} age={this.state.age} /> */}

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

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

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

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

                        </div>

                )

        }

}

ReactDOM.render(<App />,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

引入库:<script src="../js/prop-types"></script>

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(

                        <div>

                                <ul>name:{name}</ul>

                                <ul>age:{age}</ul>

                                <ul>single:{single}</ul>

                        </div>

                )

        }

}

//验证: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 {...student}/>,document.getElementById("app"))

一个组件实现任务列表

 

页面显示:

                <div>

                        <h1>Today Tasks:0</h1>

                        <!--添加任务-->

                        <div>

                                <input type="text" />

                                <button>add Task</button>

                        </div>

                        <!--任务列表-->

                        <div>

                                <ul>

                                        <li> 0--eatting--2022/09/03 </li><button>delete</button>

                                        <li> 0--eatting--2022/09/03 </li><button>delete</button>

                                        <li> 0--eatting--2022/09/03 </li><button>delete</button>

                                </ul>

                        </div>

                </div>

页面重构:

受控组件写法

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(){

                <div>

<h1>Today Tasks:{this.state.tasks.length}</h1>

                        <!--添加任务-->

<div>

        <input type="text" value={this.state.task} //双向绑定

                onChange={this.handleChange}/>

        <button onClick={this.handleAddTask}>add Task</button>

</div>

                        <!--任务列表-->

<div>

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

                <li key={index}>

                        <span>{index+1}--{task}--{this.state.date}</span>

                         <button onClick={this.handleDelete.bind(this,index)}>delete</button>

                </li> ) }) }

        </ul>

</div>

        </div>

        }

}

ReactDOM.render(<App />,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(

                <div>

                        <h1>Today Tasks:{this.state.tasks.length}</h1>

                        <AddTask addTask = {this.addTask}/>

                        <TaskList tasks = {this.state.tasks} deleteTask = {this.deleteTask}/>

                </div>

                )

        }

}

//添加任务

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(

                <div>

                        <input type="text" value={ths.state.task} onChange={this.handleChange}/>

                        <button onClick={this.handleAddTask}>add Task</button>

                </div>

                )

        }

}

//任务列表

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

function TaskList(props){

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

        return(

                <ul>

                        {

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

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

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

                                })

                        }

                        <TaskItem />

                </ul>

        )

}

function TaskItem(props){

        function handleDelete(){

                props.deleteTask(props.index)

        }

        //调用父组件删除

        return(

<li key={index}>

        <span>{props.index+1}--{props.task}--{props.date}</span>

         <button onClick={()=>{

                props.dleteTask(props.index)

        }}>delete</button>

</li>

        )

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值