本教程总共5篇,每日更新一篇,请关注我们!你可以进入历史消息查看以往文章,也敬请期待我们的新文章!
1.React 技巧1(状态组件与无状态组件的使用) ----2018.01.04
2.React 技巧2(避免无意义的父节点)----2018.01.05
3.React 技巧3(如何优雅的渲染一个List)----2018.01.06
4.React 技巧4(如何处理List里面的Item)----2018.01.07
5.React 技巧5(TodoList实现)----2018.01.08
6.React技巧6(TodoList实现2组件之间传递数据)---2018.01.09(新增)
7.React技巧7(TodoList实现3组件之间传递数据之优化)---2018.01.10(新增)
开发环境:Windows 8,node v8.9.1,npm 5.5.1,WebStorm 2017.2.2
我们看下上节课程 React技巧5(TodoList实现),我们改造下工程,复制出来一份,为demo2
因为是新的页面,我们在 config -> entry -> entry.js 里新增一个json对象,demo2
然后
npm run devNew
npm run dev
看下浏览器
OK 正常,
我们这节课在这个demo2讲解!
假设我们要实现这样的需求:
1、显示三块内容,全部、未删除、已删除
2、未删除后面有删除按钮
3、已删除后面恢复按钮
最后的效果如下:
好,我们现在开始开发:
1、显示三块内容,全部、未删除、已删除
先把LIst抽出做成List组件
原来是这样:
我们的设计原则是:尽量把增、删、改、查等逻辑方法及状态放在父组件中
List组件只作为展示组件,所有它页是无状态组件!
import React from 'react'; const List = ({list}) => <div className="list"> { list.map(data => [ data.status === 1 ? <li key={data.id}> {data.title} <button onClick={() => this.handleItemDel(data.id)}>删除</button> </li> : null ]) } </div> ; export default List;
我们在父组件:TodoList中引入 List组件,并把 list状态,及删除方法传递给List组件
这里面增加了这几句代码:
import List from './List';
this.handleItemDel = this.handleItemDel.bind(this)
<List list={list} handleItemDel={this.handleItemDel}/>
相应的页需要改造下List组件代码:
import React from 'react'; const List = ({list,handleItemDel}) => <div className="list"> { list.map(data => [ data.status === 1 ? <li key={data.id}> {data.title} <button onClick={() => handleItemDel(data.id)}>删除</button> </li> : null ]) } </div> ; export default List;
这就是父组件给子组件,传递状态及方法的示列!
子组件接收到父组件状态,进行渲染。用户点击删除,子组件调用父组件删除方法,进行删除。
我们来把三块内容写出来:
这里下需要修改下 todoList.pcss
.todoList { .box{ float: left; width: 300px; } li { list-style-type: none; margin-top: 10px; } button { border: 1px solid #cccccc; border-radius: 4px; font-size: 12px; padding: 2px 10px; margin-left: 10px; } }
现在三块内容显示的都是一样的,我们来区分一下,那么我们就要给子组件转递一个标识,告诉子组件,当前应该渲染那一部分内容!
我们设定传一个type 给子组件,并且规定 0 是全部 、1是未删除、2是已删除
<div className="cont"> <div className="box"> 全部 <List list={list} handleItemDel={this.handleItemDel} type={0}/> </div> <div className="box"> 未删除 <List list={list} handleItemDel={this.handleItemDel} type={1}/> </div> <div className="box"> 已删除 <List list={list} handleItemDel={this.handleItemDel} type={2}/> </div> </div>
然后我们修改下,List组件:
{ list.map(data => [ type === 0 ? <li key={data.id}> {data.title} <button onClick={() => handleItemDel(data.id)}>删除</button> </li> : type === 1 && data.status === 1 ? <li key={data.id}> {data.title} <button onClick={() => handleItemDel(data.id)}>删除</button> </li> : type === 2 && data.status === 0 ? <li key={data.id}> {data.title} <button onClick={() => handleItemDel(data.id)}>删除</button> </li> : null ]) }
看下浏览器
2、未删除后面有删除按钮
3、已删除后面恢复按钮
这两个需求我们一起来实现
首先,未删除的现在有删除按钮,我们先把已删除那块内容,按钮变成恢复按钮,并写上逻辑
修改 TodoList.jsx
this.handleItemRecovery = this.handleItemRecovery.bind(this)
handleItemRecovery(id) { let list = this.state.list; list.find(data => data.id === id).status = 1; this.setState({list: list}) }
<div className="box"> 已删除 <List list={list} handleItemRecovery={this.handleItemRecovery} type={2}/> </div>
看下浏览器
目前已经可以恢复了!
我们还得修改下,全部这一块的按钮,
为了直观一点,我们加上样式!
.todoList { .box{ float: left; width: 300px; } li { list-style-type: none; margin-top: 10px; } button { border: none; border-radius: 4px; font-size: 12px; padding: 2px 10px; margin-left: 10px; } .del{ background-color: #f00000; color: #FFFFFF; } .recovery{ background-color: chartreuse; } }
修改下TodoList.jsx
修改下List 组件
{ data.status === 1 ? <button onClick={() => handleItemDel(data.id)} className="del">删除</button> : <button onClick={() => handleItemRecovery(data.id)} className="recovery">恢复</button> }
以上两个组件完整代码如下:
TodoList.jsx
import React from 'react'; import List from './List'; import '../../../public/css/todoList.pcss'; class TodoList extends React.Component { constructor(props) { super(props); this.state = { list: [] }; this.handleAdd = this.handleAdd.bind(this); this.handleItemDel = this.handleItemDel.bind(this); this.handleItemRecovery = this.handleItemRecovery.bind(this) } handleAdd() { let item = this.refs['todoInput'].value; if (item) { let list = this.state.list; list.push({id: list.length + 1, title: item, status: 1}); this.setState({list: list}, () => console.log(this.state.list)) } else { alert('不能为空') } } handleItemDel(id) { let list = this.state.list; list.find(data => data.id === id).status = 0; this.setState({list: list}) } handleItemRecovery(id) { let list = this.state.list; list.find(data => data.id === id).status = 1; this.setState({list: list}) } componentDidMount() { } render() { let {list} = this.state; return ( <div className="todoList"> <input type="text" ref="todoInput"/> <button onClick={this.handleAdd}>添加</button> <div className="cont"> <div className="box"> 全部 <List list={list} handleItemDel={this.handleItemDel} handleItemRecovery={this.handleItemRecovery} type={0}/> </div> <div className="box"> 未删除 <List list={list} handleItemDel={this.handleItemDel} type={1}/> </div> <div className="box"> 已删除 <List list={list} handleItemRecovery={this.handleItemRecovery} type={2}/> </div> </div> </div> ); } } export default TodoList;
List.jsx
import React from 'react'; const List = ({list, handleItemDel, type, handleItemRecovery}) => <div className="list"> { list.map(data => [ type === 0 ? <li key={data.id}> {data.title} { data.status === 1 ? <button onClick={() => handleItemDel(data.id)} className="del">删除</button> : <button onClick={() => handleItemRecovery(data.id)} className="recovery">恢复</button> } </li> : type === 1 && data.status === 1 ? <li key={data.id}> {data.title} <button onClick={() => handleItemDel(data.id)} className="del">删除</button> </li> : type === 2 && data.status === 0 ? <li key={data.id}> {data.title} <button onClick={() => handleItemRecovery(data.id)} className="recovery">恢复</button> </li> : null ]) } </div> ; export default List;
todoList.pcss
.todoList { .box{ float: left; width: 300px; } li { list-style-type: none; margin-top: 10px; } button { border: none; border-radius: 4px; font-size: 12px; padding: 2px 10px; margin-left: 10px; } .del{ background-color: #f00000; color: #FFFFFF; } .recovery{ background-color: chartreuse; } }
我们来看下浏览器效果。
本文完
禁止擅自转载,如需转载请在公众号中留言联系我们!
感谢童鞋们支持!
如果你有什么问题,可以在下方留言给我们!