todolist组件的拆分和父子组件传值
1 /** 2 - 在上一篇博客中我们做的todolist,他只有一个组件。就是App.js组件。上篇链接:https://www.cnblogs.com/boye-1990/p/11364246.html 3 - 其实我们可以将input框,按钮都拆分成一个组件,每一个li也可以分成一个组件去渲染。 4 - 现在我们尝试将每一个li拆成一个组件去渲染。 5 */
第一步:在src目录下创建一个item.js
1 /** 2 - 代码如下 3 */ 4 import React, {Component, Fragment} from 'react'; 5 6 class Item extends Component { 7 constructor(props){ 8 super(props); 9 } 10 render(){ 11 return( 12 <Fragment> 13 <div>item</div> 14 </Fragment> 15 ) 16 } 17 } 18 19 export default Item
第二步:将item组件引入App.js组件中
1 /** 2 - 将item组件引入App组件之后,将li标签替换掉 3 - 代码如下 4 - 此时我们每点击一次提交按钮下面就会渲染一个item标签,但是内容一直都是item,因为我们在组件中写死了内容 5 */ 6 import React, { Component, Fragment }from 'react'; 7 import Item from './item.js' // 引入item组件 8 9 class App extends Component { 10 constructor(props){ 11 super(props); 12 this.state = { 13 inputValue: '',// 用来存储 input框中的 value值。 14 list:[] // 用来存储 每一个li的 value值。 15 } 16 } 17 handleInputChange = (e) => { 18 this.setState({ 19 inputValue: e.target.value 20 }) 21 console.log(e.target) 22 } 23 addList = () => { 24 this.setState({ 25 list: [...this.state.list, this.state.inputValue], 26 inputValue: '' // 添加完毕以后清空input框 27 }) 28 } 29 deletListItem(index) { // 因为在绑定该方法的时候使用了bind函数,所以这里可以不实用箭头函数去保证this的指向 30 console.log(index) 31 let list = this.state.list; 32 list.splice(index, 1); 33 console.log(list) 34 this.setState({ 35 list: [...list] 36 }) 37 } 38 render(){ 39 return ( 40 <Fragment> 41 <div> 42 <input 43 onChange = { this.handleInputChange } 44 value = {this.state.inputValue} 45 /> 46 <button onClick = { this.addList }>提交</button> 47 </div> 48 <ul> 49 { 50 this.state.list.map((item, index) => { 51 return( 52 <Item></Item> { /** 替换li标签 */ } 53 ) 54 }) 55 } 56 </ul> 57 </Fragment> 58 ); 59 } 60 } 61 export default App;
第三步:父组件给子组件传值
1 /** 2 - 上一步我们实现了item组件的拆分和引用,但是数据没有同步 3 - 我们需要将父组件中inputValue传递给item组件 4 - 父组件传值给子组件,是通过属性传值。子组件通过this.props去获取父组件传递值。 5 - item.js代码如下 6 */ 7 import React, {Component, Fragment} from 'react'; 8 9 class Item extends Component { 10 constructor(props){ 11 super(props); 12 } 13 render(){ 14 return( 15 <Fragment> 16 <div>{this.props.value}</div> {/**通过this.props来获取父组件传递过来的参数*/} 17 </Fragment> 18 ) 19 } 20 } 21 22 export default Item
1 /** 2 - App.js组件代码如下 3 */ 4 import React, { Component, Fragment }from 'react'; 5 import Item from './item.js' 6 7 class App extends Component { 8 constructor(props){ 9 super(props); 10 this.state = { 11 inputValue: '',// 用来存储 input框中的 value值。 12 list:[] // 用来存储 每一个li的 value值。 13 } 14 } 15 handleInputChange = (e) => { 16 this.setState({ 17 inputValue: e.target.value 18 }) 19 console.log(e.target) 20 } 21 addList = () => { 22 this.setState({ 23 list: [...this.state.list, this.state.inputValue], 24 inputValue: '' // 添加完毕以后清空input框 25 }) 26 } 27 deletListItem(index) { // 因为在绑定该方法的时候使用了bind函数,所以这里可以不实用箭头函数去保证this的指向 28 console.log(index) 29 let list = this.state.list; 30 list.splice(index, 1); 31 console.log(list) 32 this.setState({ 33 list: [...list] 34 }) 35 } 36 render(){ 37 return ( 38 <Fragment> 39 <div> 40 <input 41 onChange = { this.handleInputChange } 42 value = {this.state.inputValue} 43 /> 44 <button onClick = { this.addList }>提交</button> 45 </div> 46 <ul> 47 { 48 this.state.list.map((item, index) => { 49 return( 50 51 <Item 52 value={item} 53 deletItem = {this.state.deletListItem} 54 ></Item> {/** 通过属性传递给子组件 */} 55 56 ) 57 }) 58 } 59 </ul> 60 </Fragment> 61 ); 62 } 63 } 64 export default App;
第四步:子组件给父组件传值
1 /** 2 - 上一步通过父组件传值给子组件,我们解决了增加的功能,让item的value能同步input提交的数据 3 - 现在我们需要完成删除的功能,删除我们需要将item的key值传递给父组件,让他删除list数组中对应的元素 4 - 如何达到效果呢,我们还是需要父组件将删除的方法传递给子组件,再在子组件中去执行他 5 - App.js代码如下 6 */ 7 import React, { Component, Fragment }from 'react'; 8 import Item from './item.js' 9 10 class App extends Component { 11 constructor(props){ 12 super(props); 13 this.state = { 14 inputValue: '',// 用来存储 input框中的 value值。 15 list:[] // 用来存储 每一个li的 value值。 16 } 17 } 18 handleInputChange = (e) => { 19 this.setState({ 20 inputValue: e.target.value 21 }) 22 console.log(e.target) 23 } 24 addList = () => { 25 this.setState({ 26 list: [...this.state.list, this.state.inputValue], 27 inputValue: '' // 添加完毕以后清空input框 28 }) 29 } 30 deletListItem = (index) => { // 因为在绑定该方法的时候使用了bind函数,所以这里可以不实用箭头函数去保证this的指向 31 console.log(index) 32 let list = this.state.list; 33 list.splice(index, 1); 34 console.log(list) 35 this.setState({ 36 list: [...list] 37 }) 38 } 39 render(){ 40 return ( 41 <Fragment> 42 <div> 43 <input 44 onChange = { this.handleInputChange } 45 value = {this.state.inputValue} 46 /> 47 <button onClick = { this.addList }>提交</button> 48 </div> 49 <ul> 50 { 51 this.state.list.map((item, index) => { 52 return( 53 54 <Item 55 value = {item} 56 index = {index} 57 deletItem = {this.deletListItem} 58 ></Item> 59 60 ) 61 }) 62 } 63 </ul> 64 </Fragment> 65 ); 66 } 67 } 68 export default App;
1 /** 2 - item.js代码如下 3 */ 4 import React, {Component, Fragment} from 'react'; 5 6 class Item extends Component { 7 constructor(props){ 8 super(props); 9 } 10 deletItem = () => { 11 this.props.deletItem(this.props.index) 12 console.log(this.props.index) 13 } 14 render(){ 15 return( 16 <Fragment> 17 <div 18 onClick = {this.deletItem} 19 > 20 {this.props.value} 21 </div> 22 </Fragment> 23 ) 24 } 25 } 26 27 export default Item
总结
1 /** 2 3 - 通过以上几步我们以及将li拆分成一个组件了。 4 - 但是在父组件传递给子组件函数的时候,需要注意一点,如果你所传递的函数是箭头函数,可以直接传递就如上面代码一样 5 - 如果你所传递的函数是一个非箭头函数,需要通过bind(this)强行将这个函数的this指向父组件,不然在子组件中使用的时候this是指向子组件的,子组件是没有父组件的函数的。 6 - 另外这次拆分还有一项警告没有解决index.js:1375 Warning: Each child in a list should have a unique "key" prop. 7 - 下次更新解决 8 */