专栏首页前端人人React技巧6(TodoList实现2组件之间传递数据)

React技巧6(TodoList实现2组件之间传递数据)

本教程总共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;
  }
}

我们来看下浏览器效果。

本文分享自微信公众号 - 前端人人(frontend_everyone),作者:思铭

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-01-09

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • React技巧7(TodoList实现3组件之间传递数据之优化)

    本教程总共5篇,每日更新一篇,请关注我们!你可以进入历史消息查看以往文章,也敬请期待我们的新文章! 1.React 技巧1(状态组件与无状态组件的使用) --...

    前端人人
  • React第三方组件6(状态管理之Mobx的使用④TodoList下)

    本教程总共5篇,每日更新一篇,请关注我们!你可以进入历史消息查看以往文章,也敬请期待我们的新文章! 1、React第三方组件6(状态管理之Mobx的使用①简单...

    前端人人
  • React技巧4(如何处理List里面的Item)

    本教程总共5篇,每日更新一篇,请关注我们!你可以进入历史消息查看以往文章,也敬请期待我们的新文章! 1.React 技巧1(状态组件与无状态组件的使用) --...

    前端人人
  • 充斥着未来感的AI房间:觉得你有趣就会笑的算法

    “The Laughing Room”是由作家,插画家和麻省理工学院研究生Jonathan Sun创作的互动艺术装置,就像一个典型的起居室:有沙发,扶手椅,咖啡...

    AiTechYun
  • AI 3 分钟:每周最新闻

    平时都是讲技术讲干货,太费脑子。周一是一周最难熬的一天,所以我们今天聊点轻松的话题。

    用户1737318
  • Spark2.3.0 创建RDD

    Spark的核心概念是弹性分布式数据集(RDD),RDD 是一个可容错、并行操作的分布式元素集合。有两种方法可以创建 RDD 对象:

    smartsi
  • 全国首家百度大脑创新体验中心启动,中关村创业大街AI产业创新生态再升级

    12月26日,由百度、中关村创业大街联合打造的全国首家“百度大脑创新体验中心”在中关村创业大街揭幕启动。

    量子位
  • Java基础语法

    Java两种循环 List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();...

    苦咖啡
  • 第176天:页面优化

    从用户角度而言,优化能够让页面加载得更快、对用户的操作响应得更及时,能够给用户提供更为友好的体验。从服务商角度而言,优化能够减少页面请求数、或者减小请求所占带宽...

    半指温柔乐
  • lodash源码分析之Hash缓存

    在那小小的梦的暖阁,我为你收藏起整个季节的烟雨。 ——洛夫《灵河》 本文为读 lodash 源码的第四篇,后续文章会更新到这个仓库中,欢迎 star:poc...

    对角另一面

扫码关注云+社区

领取腾讯云代金券