todolist组件的拆分
- 之前我们做的todolist,他只有一个组件。就是App.js组件。
- 其实我们可以将input框,按钮都拆分成一个组件,每一个li也可以分成一个组件去渲染。
- 现在我们尝试将每一个li拆成一个组件去渲染。
第一步:在src目录下创建一个item.js
import React, {Component, Fragment} from 'react';
class Item extends Component {
constructor(props){
super(props);
}
render(){
return(
<Fragment>
<div>item</div>
</Fragment>
)
}
}
export default Item
第二步:将item组件引入App.js组件中
- 将item组件引入App组件之后,将li标签替换掉
- 代码如下
- 此时我们每点击一次提交按钮下面就会渲染一个item标签,但是内容一直都是item,因为我们在组件中写死了内容
import React, { Component, Fragment }from 'react';
import Item from './item.js' // 引入item组件
class App extends Component {
constructor(props){
super(props);
this.state = {
inputValue: '',// 用来存储 input框中的 value值。
list:[] // 用来存储 每一个li的 value值。
}
}
handleInputChange = (e) => {
this.setState({
inputValue: e.target.value
})
console.log(e.target)
}
addList = () => {
this.setState({
list: [...this.state.list, this.state.inputValue],
inputValue: '' // 添加完毕以后清空input框
})
}
deletListItem(index) { // 因为在绑定该方法的时候使用了bind函数,所以这里可以不实用箭头函数去保证this的指向
console.log(index)
let list = this.state.list;
list.splice(index, 1);
console.log(list)
this.setState({
list: [...list]
})
}
render(){
return (
<Fragment>
<div>
<input
onChange = { this.handleInputChange }
value = {this.state.inputValue}
/>
<button onClick = { this.addList }>提交</button>
</div>
<ul>
{
this.state.list.map((item, index) => {
return(
<Item></Item> { /** 替换li标签 */ }
)
})
}
</ul>
</Fragment>
);
}
}
export default App;
第三步:父组件给子组件传值
- 上一步我们实现了item组件的拆分和引用,但是数据没有同步
- 我们需要将父组件中inputValue传递给item组件
- 父组件传值给子组件,是通过属性传值。子组件通过this.props去获取父组件传递值。
- item.js代码如下
import React, {Component, Fragment} from 'react';
class Item extends Component {
constructor(props){
super(props);
}
render(){
return(
<Fragment>
<div>{this.props.value}</div> {/**通过this.props来获取父组件传递过来的参数*/}
</Fragment>
)
}
}
export default Item
import React, { Component, Fragment }from 'react';
import Item from './item.js'
class App extends Component {
constructor(props){
super(props);
this.state = {
inputValue: '',// 用来存储 input框中的 value值。
list:[] // 用来存储 每一个li的 value值。
}
}
handleInputChange = (e) => {
this.setState({
inputValue: e.target.value
})
console.log(e.target)
}
addList = () => {
this.setState({
list: [...this.state.list, this.state.inputValue],
inputValue: '' // 添加完毕以后清空input框
})
}
deletListItem(index) { // 因为在绑定该方法的时候使用了bind函数,所以这里可以不实用箭头函数去保证this的指向
console.log(index)
let list = this.state.list;
list.splice(index, 1);
console.log(list)
this.setState({
list: [...list]
})
}
render(){
return (
<Fragment>
<div>
<input
onChange = { this.handleInputChange }
value = {this.state.inputValue}
/>
<button onClick = { this.addList }>提交</button>
</div>
<ul>
{
this.state.list.map((item, index) => {
return(
<Item
value={item}
deletItem = {this.state.deletListItem}
></Item> {/** 通过属性传递给子组件 */}
)
})
}
</ul>
</Fragment>
);
}
}
export default App;
第四步:子组件给父组件传值
- 上一步通过父组件传值给子组件,我们解决了增加的功能,让item的value能同步input提交的数据
- 现在我们需要完成删除的功能,删除我们需要将item的key值传递给父组件,让他删除list数组中对应的元素
- 如何达到效果呢,我们还是需要父组件将删除的方法传递给子组件,再在子组件中去执行他
- App.js代码如下
import React, { Component, Fragment }from 'react';
import Item from './item.js'
class App extends Component {
constructor(props){
super(props);
this.state = {
inputValue: '',// 用来存储 input框中的 value值。
list:[] // 用来存储 每一个li的 value值。
}
}
handleInputChange = (e) => {
this.setState({
inputValue: e.target.value
})
console.log(e.target)
}
addList = () => {
this.setState({
list: [...this.state.list, this.state.inputValue],
inputValue: '' // 添加完毕以后清空input框
})
}
deletListItem = (index) => { // 因为在绑定该方法的时候使用了bind函数,所以这里可以不实用箭头函数去保证this的指向
console.log(index)
let list = this.state.list;
list.splice(index, 1);
console.log(list)
this.setState({
list: [...list]
})
}
render(){
return (
<Fragment>
<div>
<input
onChange = { this.handleInputChange }
value = {this.state.inputValue}
/>
<button onClick = { this.addList }>提交</button>
</div>
<ul>
{
this.state.list.map((item, index) => {
return(
<Item
value = {item}
index = {index}
deletItem = {this.deletListItem}
></Item>
)
})
}
</ul>
</Fragment>
);
}
}
export default App;
import React, {Component, Fragment} from 'react';
class Item extends Component {
constructor(props){
super(props);
}
deletItem = () => {
this.props.deletItem(this.props.index)
console.log(this.props.index)
}
render(){
return(
<Fragment>
<div
onClick = {this.deletItem}
>
{this.props.value}
</div>
</Fragment>
)
}
}
export default Item
总结
- 通过以上几步我们以及将li拆分成一个组件了。
- 但是在父组件传递给子组件函数的时候,需要注意一点,如果你所传递的函数是箭头函数,可以直接传递就如上面代码一样
- 如果你所传递的函数是一个非箭头函数,需要通过bind(this)强行将这个函数的this指向父组件,不然在子组件中使用的时候this是指向子组件的,子组件是没有父组件的函数的。
- 另外这次拆分还有一项警告没有解决index.js:1375 Warning: Each child in a list should have a unique "key" prop.
- 下次更新