React实践项目–todolist(3)基本组件的编写与联调

React实践项目--todolist(3)基本组件的编写与联调
TodoList

真正的挑战要开始了~~~

这里我采用自顶向下的叙述方法,来描述组件的结构,大家可以先按照顺序依次阅读,最后再回头完整的看一遍,就能明白其中的设计方法啦~~

  1. App.jsx

在根组件中,我们使用 TodoListContext.Consumer 将从模拟接口获取的数据,传递给数据消费者,即 TodoList 组件。

在未获取到数据前,使用 Loading 组件来渲染当前区域。


import "./App.css";

import Loading from "./components/Loading";

import TodoList from "./components/TodoList";

import { Http, TodoListContext } from "./utils";



function App({

  return (

    <div className="App">

      <Http.Get url="xxx" loading={<Loading />}>

        <TodoListContext.Consumer>

          {(value) => <TodoList listData={value} />}

        </TodoListContext.Consumer>

      </Http.Get>

    </div>


  );

}



export default App;

  1. TodoList

import React from "react";

import "./index.css";

import TodoItem from "../TodoItem";

import InputItem from "../InputItem";

import TodoTabs from "../TodoTabs";



export default class TodoList extends React.Component {

  state = {

    filterType"",

    listData: [],

    originData: [],

  };

  // 存储 listData

  async componentDidMount() {

    this.setState({

      listDatathis.props.listData,

      originDatathis.props.listData,

    });

  }



  // 点击 input: checkbox ,把当前任务置为已完成

  complate(name) {

    this.setState({

      listData: [

        ...this.state.listData.map((item) => {

          if (item.name === name) {

            item.isChecked = !item.isChecked;

          }

          return item;

        }),

      ],

    });

  }



  // 删除列表项

  deleteItem(name) {

    this.setState({

      listData: [...this.state.listData.filter((item) => item.name !== name)],

    });

  }

  // 增加列表项

  addItem(name) {

    if (name.trim()) {

      this.setState({

        listData: [

          ...this.state.listData,

          {

            name,

            isDeletefalse,

            isCheckedfalse,

          },

        ],

      });

    }

  }



  // 设置当前过滤的类型

  filterListData(filter) {

    this.setState({

      filterType: filter,

    });

  }



  render() {

    const listData = this.state.listData.filter(

      (item) => !!item[this.state.filterType || "name"]

    );

    return (

      <div className="todo_wrapper">

        <InputItem

          listData={this.state.listData}

          addItem={this.addItem.bind(this)}

        />


        <TodoTabs

          filterType={this.state.filterType}

          filterListData={this.filterListData.bind(this)}

        />


        <ul>

          {listData.length ? (

            listData.map((item, index) => (

              <TodoItem

                key={index}

                data={item}

                complate={this.complate.bind(this, item.name)}

                deleteItem={this.deleteItem.bind(this, item.name)}

              />


            ))

          ) : (

            <div>没有数据</div>

          )}

        </ul>

      </div>


    );

  }

}


.todo_wrapper{

  width500px;

  margin: auto;

  padding50px 0;

  ul{

    padding0;

  }

}

  1. InputItem

React.createRef 创建引用,来获取输入框的 value


import React from "react";

import "./index.scss";



export default class InputItem extends React.Component {

  constructor(props) {

    super(props);

    this.InputRef = React.createRef();

  }



  state = {

    addItem"",

  };



  // 增加列表项

  addItem() {

    this.props.addItem(this.InputRef.current.value);

    this.InputRef.current.value = "";

  }



  render() {

    return (

      <div className="input_wrapper">

        <input type="text" placeholder="请输入待办事项" ref={this.InputRef} />

        <button onClick={() => this.addItem()}>增加</button>

      </div>


    );

  }

}




.input_wrapper {

  display: flex;

  align-items: center;

  height30px;



  input {

    flex1;

    height100%;

    margin-right10px;

    outline: none;

    padding-left1em;

    border1px solid #ccc;

  }



  button {

    width100px;

    height100%;

    border: none;

    cursor: pointer;

    transition: all .3s;



    &:hover {

      background-color: black;

      color#fff;

    }

  }

}

  1. TodoTabs

这个组件可以切换要展示的不同列表项:全部/已完成

当点击某个类型时,通过 props 调用父组件的 filterListData 方法过滤数据


import React from "react";

import "./index.scss";



export default class TodoTabs extends React.Component {

  state = {

    selIdx0,

    tabList: [

      {

        name"全部",

        filter"",

      },

      {

        name"已完成",

        filter"isChecked",

      },

    ],

  };



  // 选择某个数据类型

  setSelIdx(idx) {

    this.setState({

      selIdx: idx,

    });

    const { selIdx, tabList } = this.state;

    // 调用父组件的方法,并将类型通过参数传给父组件

    this.props.filterListData(tabList[selIdx].filter);

  }



  render() {

    return (

      <div className="tabs">

        {this.state.tabList.map((item, index) => (

          <div

            key={index}

            className={`tab ${this.props.filterType === item.filter ? "sel: ""}`}

            onClick={()=>
this.props.filterListData(item.filter)}

          >

            {item.name}

          </div>

        ))}

      </div>


    );

  }

}


.tabs {

  display: flex;



  .tab {

    width80px;

    margin20px 10px 10px 0;

    padding5px 10px;

    border1px solid #ccc;

    box-sizing: border-box;

    cursor: pointer;

    transition: all .3s;



    &.sel,

    &:hover {

      background-color#000;

      color#fff;

    }

  }

}

  1. TodoItem

待办列表项


import React from "react";

import IsChecked from "../IsCheck";

import "./index.scss";



export default class TodoItem extends React.Component {

  render() {

    const { name, isChecked, isDelete } = this.props.data;

    return (

      <div className="todo_item">

        <div className="left">

          <IsChecked isChecked={isChecked} complate={this.props.complate} />

          <span className={isChecked ? "del: ""}>{name}</span>

        </div>

        <button onClick={this.props.deleteItem}>删除</button>

      </div>


    );

  }

}


.todo_item {

  display: flex;

  align-items: center;

  justify-content: space-between;

  height30px;

  margin-bottom10px;



  .left {

    flex1;

    display: flex;

    align-items: center;

    margin-right20px;

    text-align: left;



    span.del {

      flex1;

      text-decoration: line-through;

    }

  }



  button {

    width100px;

    height100%;

    border: none;

    cursor: pointer;

    transition: all .3s;



    &:hover {

      background-color: black;

      color#fff;

    }

  }

}

  1. IsChecked

操作待办事项


import React from 'react';

import './index.scss'



export default class IsChecked extends React.Component{

  

  render(){

    return (

      <input type="checkbox" checked={this.props.isChecked} onChange={this.props.complate} />

    )

  }

}


input[type="checkbox"]{

  width20px;

  height20px;

  border-radius50%;

}


原文始发于微信公众号(前端华先生):React实践项目–todolist(3)基本组件的编写与联调

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/55323.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!