课程名称
课程章节
第3章 React基础精讲
-3-5 拆分组件与组件之间的传值 (24:29)
课程讲师
课程内容
-
拆分组件与组件之间的传值
拆分TodoList的组件 =>
● 上面的内容:输入内容、input框、提交按钮
● 下面的内容:list
列表组件 => TodoItem -
组件化的思想
-
父组件向子组件传递数据
TodoItem组件实际上,是需要获取到我们在input输入的内容,然后显示出来的。
这就需要父组件向子组件传递显示的数据了,这样的话,子组件才能做灵活的显示了。父组件需要通过属性的方式进行传递,将item起名叫content传递给子组件。
子组件通过this.props获取并使用即可。
原理:当在input里提交数据时,对应数组中也会增加该数据,这个时候render函数会重新去执行,即进行页面的重新渲染,就会把item传递通过content给子组件TodoItem的props属性。 -
子组件向父组件传递数据
课程收获
拆分组件与组件之间的传值
一个大的页面,操作逻辑就会比较复杂。如果将一个大的页面拆分成很多个组件,那么单个组件的操作逻辑就较为简答了。
拆分TodoList的组件 =>
● 上面的内容:输入内容、input框、提交按钮
● 下面的内容:list
列表组件 => TodoItem
import React, {Component} from "react";
class TodoItem extends Component{
render(){
return(
<div>TodoItem</div>
)
}
}
export default TodoItem;
父组件TodoList去使用TodoItem组件,需要引入import,之前在ul中循环list数据,创建li标签。现在不渲染li标签了,而是渲染TodoItem标签。
...
import TodoItem from "./TodoItem"
...
render(){
return (
<Fragment>
<div>
<label htmlFor="InputArea">输入内容</label>
<input
id="InputArea"
className="input"
value={this.state.inputValue}
onChange={this.handleInputChange.bind(this)}
></input>
<button onClick={this.handleBtnClick.bind(this)}>提交</button>
</div>
<ul>
{
this.state.list.map((item,index) => {
// return <li
// key={index}
// onClick={this.handleDelItem.bind(this, index)}
// dangerouslySetInnerHTML={{__html:item}}
// ></li>
return <TodoItem/>
})
}
</ul>
</Fragment>
)
}
现在输入内容也不管用了,显示的都是TodoItem组件了。
实际上写一个React项目时,使用组件化的思想,一般结构如下:
在最顶部有一个组件,对应这个项目,其实就是TodoList组件,下一层的组件就是TodoItem组件。实际上,当项目开始复杂后,TodoItem组件还可以向下拆分成更多的组件,这样子组件就越来越多,实际组件化思想开发,项目的组件结构就是一个树型的结构了。
父组件向子组件传递数据
TodoItem组件实际上,是需要获取到我们在input输入的内容,然后显示出来的。
这就需要父组件向子组件传递显示的数据了,这样的话,子组件才能做灵活的显示了。父组件需要通过属性的方式进行传递,将item起名叫content传递给子组件。
return <TodoItem content={item}/>
子组件通过this.props获取并使用即可。
class TodoItem extends Component{
render(){
return(
<div>{this.props.content}</div>
)
}
}
原理:当在input里提交数据时,对应数组中也会增加该数据,这个时候render函数会重新去执行,即进行页面的重新渲染,就会把item传递通过content给子组件TodoItem的props属性。
子组件向父组件传递数据
实现:点击list的时候,列表项能够从列表中删除。
这就需要绑定一个事件了,不是给TodoItem绑定事件,还是进该组件里绑定事件,即div标签。
列表中显示项,是通过list数组渲染出来的,删除功能实际是操作删除数组里的对应项。
子组件如何去修改父组件的数据呢?
实际不允许子组件直接修改父组件的,而是通过调用父组件的方法。
之前实现的删除方法,参数是index,那么在子组件中是需要传递index的,可通过父组件传递index到子组件,子组件再调用父组件方法时传参即可。
this.handleClick.bind(this) 这种绑定事件处理函数的方法,后期很浪费性能,可以这样写:
constructor(props){
super(props);
this.handleClick = this.handleClick.bind(this);
}
ind 的操作放在构造函数里去做,省去多次render每次都bind了,这样就节约了一些性能。
子组件想改变父组件的内容,则需要调用父组件的handleDelItem(index)方法,并传递参数。
父组件应当把它自己的方法传递给子组件。
import React, { Component, Fragment } from "react";
import "./style.css"
import TodoItem from "./TodoItem"
class TodoList extends Component {
constructor(props){
super(props);
this.state = {
inputValue: "",
list: ["完成数学作业","完成语文作业"]
}
}
render(){
return (
<Fragment>
<div>
<label htmlFor="InputArea">输入内容</label>
<input
id="InputArea"
className="input"
value={this.state.inputValue}
onChange={this.handleInputChange.bind(this)}
></input>
<button onClick={this.handleBtnClick.bind(this)}>提交</button>
</div>
<ul>
{
this.state.list.map((item,index) => {
return <TodoItem
content = {item}
index = {index}
deleteItem = {this.handleDelItem}
/>
})
}
</ul>
</Fragment>
)
}
handleInputChange(e){
// console.log(this)
// this.state.inputValue = e.target.value;
this.setState({
inputValue: e.target.value
})
}
handleBtnClick(){
this.setState({
list:[...this.state.list, this.state.inputValue],
inputValue:""
})
}
handleDelItem(index){
const dest = [...this.state.list];
dest.splice(index, 1);
// this.state.list.splice(index, 1);
this.setState({
list: dest
// list: this.state.list
})
}
}
export default TodoList;
import React, {Component} from "react";
class TodoItem extends Component{
constructor(props){
super(props);
this.handleClick = this.handleClick.bind(this);
}
render(){
return(
<div onClick={this.handleClick}>{this.props.content}</div>
)
}
handleClick(){
this.props.deleteItem(this.props.index);
}
}
export default TodoItem;
点击列表项,报错了。
因为传递的方法this,到了子组件时候当前this下就没有deleteItem方法了,这个时候就需要this指向,指向父组件了。
<ul>
{
this.state.list.map((item,index) => {
// return <li
// key={index}
// onClick={this.handleDelItem.bind(this, index)}
// dangerouslySetInnerHTML={{__html:item}}
// ></li>
return <TodoItem
content = {item}
index = {index}
deleteItem = {this.handleDelItem.bind(this)}
/>
})
}
</ul>
总结
● 组件拆分
● 父子组件的关系,数据相互传递
○ 父 => 子,可以传递数据,也可方法
○ 子 => 父,调用父组件的方法来操作父组件的数据,注意父组件的this指向一定进行绑定。