react实现todolist的增删改查详解

 更新时间:2021年12月24日 16:47:57   作者:lxslxskxs  
这篇文章主要为大家介绍了react实现todolist的增删改查,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

以todolist为例

在这里插入图片描述

在这里插入图片描述

目录如下

在这里插入图片描述

app.js

 import React, {  PureComponent } from 'react'
import Input from './components/Input'
import List from './components/List'
import Total from './components/Total'
import Mask from './components/Mask'
import { bus as $bus } from './components/bus'
import './App.css'
export default class App extends PureComponent {
  constructor() {
    super()
    this.state = {
      flag: false,
      list: [
        {
          id: 1,
          content: '哈哈哈',
          checked: false
        },
        {
          id: 7,
          content: '哈哈哈',
          checked: false
        },
        {
          id: 5,
          content: '哈哈哈',
          checked: false
        },
      ],
      checkAll: false,
      selectLength: 0,
      item: {}
    }
  }
  // 全选全不选
  checkAllHandler(checked) {
    console.log("checked",checked);
    const { list } = this.state
    const newList = list.map(item =>{
      return {...item,checked}
    })
    this.setState({list:newList,checkAll: checked},()=>{
      this.doneLenth()
    })
  }
  // 单选单不选
  checkHandler =(id,checked)=> {
    const { list } = this.state
    const newList = list.map(item => {
      return item.id === id ? {...item,checked} : item
    })
    let checkAll = newList.length && newList.every(item => item.checked)
    this.setState(() => ({list: newList,checkAll}),()=>{
      this.doneLenth()
    })
  }
  // 添加 
  addHandler = (obj)=>{
    let { list } = this.state;
    let newList = [...list,obj]
    console.log('newList===='+newList)
    this.setState({
      list: newList,
    },()=>{
      this.doneLenth()
    })
  } 
  // 搜索
  searchHandler=(content)=>{
    console.log("content",content);
    let { list } = this.state;
    let newList = list.filter(item => item.content.includes(content))
    this.setState({
      list: newList
    },()=>{
      this.doneLenth()
    })
  }
  // 删除
  delHandler = (id)=> {
    console.log("id",id);
    const { list } = this.state
    const newList = list.filter(item => item.id !=id)
    let checkAll = newList.length && newList.every(item => item.checked)
    this.setState(() => ({list: newList,checkAll}),()=>{
      this.doneLenth()
    })
  }
  // 编辑
  editHandler = (items)=>{
    this.setState({
      item: items
    })
  }
  // 更新
  update = (content)=>{
    const { list,item } = this.state
    let obj = Object.assign(item,{content})
    const newList = list.map(v =>{
      if(v.id === obj.id) {
        v = {...obj}
      }
      return v
    })
    this.setState({
      list: newList,
      item: obj
    })
  }
  // 已完成 
  doneLenth=()=> {
    const { list } = this.state
    const newList = list.filter(item => item.checked)
    let selectLength = newList.length
    setTimeout(()=>{
      this.setState({
        selectLength
      })
    })
  }
  // 挂载
  componentDidMount() {
    this.unSubscribe = $bus.addListener("getFlag",(flag)=>{
      this.setState({flag})
    })
    this.unSubscribe1 = $bus.addListener("sendValue",(obj)=>{
     this.addHandler(obj)
    })
    this.unSubscribe2 = $bus.addListener("searchValue",(value)=>{
     this.searchHandler(value)
    })
    this.unSubscribe3 = $bus.addListener("getItem",(item)=>{
     this.editHandler(item)
    })
    this.unSubscribe4 = $bus.addListener("update",(content)=>{
     this.update(content)
    })
  }
  // 卸载
  componentWillUnmount() {
    $bus.removeListener(this.unSubscribe)
    $bus.removeListener(this.unSubscribe1)
    $bus.removeListener(this.unSubscribe2)
    $bus.removeListener(this.unSubscribe3)
    $bus.removeListener(this.unSubscribe4)
  }
  render() {
    let { flag, list,checkAll,selectLength } = this.state
    return (
      <div className='container'>
        {/* 输入框 */}
        <Input></Input>
        {/* 列表 */}
        <List list={list} checkHandler={this.checkHandler} delHandler={this.delHandler}></List>
        {/* 统计 */}
        <Total checkAllHandler={this.checkAllHandler.bind(this)} checkAll={checkAll} selectLength={selectLength}></Total>
        {/* 编辑弹框 */}
        { flag ? <Mask ></Mask> : ''}
      </div>
    )
  }
}

Input.js

import React, { Component } from 'react'
import { bus as $bus } from './bus'
export default class Input extends Component {
  constructor() {
    super()
    this.state = {
      value:""
    }
  }
  changeHandler = (e)=>{
    this.setState({
      value: e.target.value
    })
    console.log("this.state.value",this.state.value);
  }
  // 添加
  addHandler = ()=>{
    let { value } = this.state;
    let obj = {
      id: Date.now(),
      content: value,
      done: false
    }
    if(value) {
      $bus.emit("sendValue",obj)
    } else {
      console.log("请输入")
    }
  }
  // 搜索
  searchHandler = ()=>{
    console.log("搜索");
    let { value } = this.state;
    if(!value) return console.log("请输入");
    $bus.emit("searchValue",value)
  }
  render() {
    let { value } = this.state
    return (
      <>
        <div className="input">
          <input type="text" value={value} placeholder='请输入你的任务名称,按回车键确认' onInput={this.changeHandler}/>
          <button className="btn btn-success" onClick={this.addHandler}>添加</button>
          <button className="btn btn-primary" onClick={this.searchHandler}>搜索</button>
        </div>
      </>
    )
  }
}

List.js

import React, { Component } from 'react'
import Item from './Item'
import PropTypes from 'prop-types'
export default class List extends Component {
  static propTypes = {
		list:PropTypes.array.isRequired,
	}
  render() {
    let { list,checkHandler,checkAllHandler,delHandler } = this.props;
    console.log("list",list);
    return (
      <ul className="task-list">
        {
          list.map(item => (<Item item={item} key={item.id} checkHandler={checkHandler} checkAllHandler={checkAllHandler} delHandler={delHandler}></Item>))
        }
      </ul>
    )
  }
}

Item.js

import React, { Component } from 'react'
import { bus as $bus } from './bus'
export default class Item extends Component {
  constructor(props) {
    super(props)
    this.state = {}
  }
  changeHandler = (id)=>{
    let { checkHandler } = this.props;
    return (e)=>{
      checkHandler(id,e.target.checked)
    }
  }
  removeHandler(){
    let { delHandler } = this.props;
    delHandler(arguments[0])
  }
  editHadnler = (item)=>{
    $bus.emit("getFlag",true)
    localStorage.setItem("obj",JSON.stringify(item))
    $bus.emit("getItem",item)
  }
  render() {
    let { item } = this.props;
    return (
      <li className="task-item">
        <input type="checkbox" checked={item.checked} onChange={this.changeHandler(item.id)}/>
        <div className="content">
          {item.content}
        </div>
        <button className={`btn btn-success ${!item.checked ? "d-none" : "d-block"}`} onClick={()=> this.editHadnler(item)}>编辑</button>
        <button className={`btn btn-danger ${!item.checked ? "d-none" : "d-block"}`} onClick={this.removeHandler.bind(this,item.id)}>删除</button>
      </li>
    )
  }
}

Total.js

import React, { Component } from 'react'
export default class Total extends Component {
  constructor() {
    super()
    this.changeAllHandler = this.changeAllHandler.bind(this)
  }
  changeAllHandler(e) {
    let { checkAllHandler } = this.props
    checkAllHandler(e.target.checked)
  }
  render() {
    let { checkAll,selectLength } = this.props;
    return (
      <div className="task-done">
        <input type="checkbox" onChange={this.changeAllHandler} checked={checkAll}/>
        <p>已完成<span className="single-number">{selectLength}</span> 全部<span className="all-number">4</span></p>
      </div>
    )
  }
}

Mask.js(弹窗)

import React, { Component } from 'react'
import { bus as $bus } from './bus'
export default class mask extends Component {
  constructor() {
    super()
    this.state = {
      value: ''
    }
  }
  closeMask = ()=>{ // 关闭弹窗
    $bus.emit("getFlag",false)
  }
  updateHandler = ()=>{
    $bus.emit("getFlag",false)
    $bus.emit("update",this.state.value)
  }
  onChange = (e) =>{
    this.setState({
      value: e.target.value
    })
  }
  componentDidMount() {
    let obj = JSON.parse(localStorage.getItem("obj"))
    this.setState({
      value: obj.content
    })
  }
  render() {
    let { value } = this.state
    return (
      <div>
        <div className="mm-mask" >
        <div className="mm-modal">
          <div className="mm-title">
            <span className="mm-edit">编辑</span>
            <span className="mm-close" onClick={this.closeMask}>x</span>
          </div>
          <div className="mm-content">
            <input type="text" value={value} placeholder="任务名称" onInput={this.onChange}/>
          </div>
          <div className="mm-box-btn">
            <div className="mm-update" onClick={this.updateHandler}>更新</div>
            <div className="mm-cancel" onClick={this.closeMask}>取消</div>
          </div>
        </div>
      </div>
      </div>
    )
  }
}

bus.js

 yarn add -D events
import { EventEmitter } from 'events'
export const bus = new EventEmitter() // 导出bus实例

App.css

* {
  margin: 0;
  padding: 0;
}
input,button {
  outline: none;
  border: 0;
}
ul>li {
  list-style: none;
}
.container {
  width: 400px;
  height: 500px;
  margin: 10px auto auto;
  padding: 20px;
  box-sizing: border-box;
  color: #3333;
  border: 1px solid;
  overflow: hidden;
}
.input {
  width: 100%;
  height: 30px;
  display: flex;
}
input {
  width: 100%;
  height: 100%;
  border: 1px solid #e1e1e1;
  box-sizing: border-box;
  border-radius: 4px;
  padding: 0 10px;
}
input::placeholder {
  color: #e1e1e1;
}
input:focus {
  border: 1px solid #0096e6;
}
.task-list {
  width: 100%;
  display: flex;
  flex-flow: column wrap;
  margin-top: 10px;
}
.task-list li {
  display: flex;
  height: 40px;
  justify-content: center;
  align-items: center;
  padding: 0 10px;
  background-color: #eef0f4;
  margin-bottom: 10px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.task-list li input[type^="checkbox"] {
  width: 15px;
  height: 15px;
  border: 1px solid #e1e1e1;
  cursor: pointer;
  flex-shrink: 0;
}
.task-list li .content {
  flex: 1;
  margin-left: 10px;
}
.btn {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  height: 30px;
  justify-content: center;
  padding: 5px 10px;
  text-align: center;
  cursor: pointer;
  border-radius: 4px;
  color: #fff;
  letter-spacing: 2px;
  margin: 0 5px;
  box-sizing: border-box;
  font-size: 16px;
}
.btn-success {
  background-color: #0f0;
}
.btn-danger {
  background-color: #f00;
}
.btn-primary {
  background-color: #0096e6;
}
.task-done {
  width: 100%;
  height: 40px;
  line-height: 40px;
  display: flex;
  align-items: center;
  background-color: #eef0f4;
  padding-left: 10px;
  box-sizing: border-box;
  margin-top: 30px;
}
.task-done input {
  width: 15px;
  height: 15px;
  border: 1px solid #e1e1e1;
  cursor: pointer;
  flex-shrink: 0;
  margin-right: 10px;
}
.single-number {
  color: #333;
  margin-left: 5px;
}
.all-number {
  color: red;
  margin-left: 5px;
}
.mm-mask{
  position:fixed;
  top:0;
  left:0;
  right:0;
  bottom:0;
  background:rgba(0,0,0,0.5);
}
.mm-modal{
  width:350px;
  position:absolute;
  top:50%;
  left:50%;
  transform:translate(-50%,-50%);
  z-index:1000;
  background:#ffffff;
  border-radius:4px;
  color:#333333;
}
.mm-title {
  height:50px;
  line-height:50px;
  display:flex;
  justify-content:space-between;
  border-bottom:1px solid #e1e1e1;
  box-sizing:border-box;
  font-size:20px;
}
.mm-edit{
  text-indent:20px;
}
.mm-close{
  margin-right:20px;
  font-family:consals;
  cursor:pointer;
}
.mm-content{
  padding:0 20px;
  margin-bottom:20px;
}
.mm-content input{
  width:100%;
  height:30px;
  line-height:30px;
  text-indent:20px;
  border-radius:4px;
  margin-top:20px;
  border:1px solid #666;
  box-sizing:border-box;
}
.mm-content input:hover{
  border:1px solid #0096e6;
}
.mm-content input:last-child{
  text-indent:5px;
}
.mm-box-btn{
  display:flex;
}
.mm-update,.mm-cancel{
  width:80px;
  height:30px;
  line-height:30px;
  text-align: center;
  cursor:pointer;
  background:#0096e6;
  color:#ffffff;
  user-select:none;
  border-radius:4px;
  margin:0 20px 50px;
}
.mm-update{
  margin-right:10px;
}
.d-none {
  display: none;
}
.d-block {
  display: block;
}

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

相关文章

  • React-native桥接Android原生开发详解

    React-native桥接Android原生开发详解

    本篇文章主要介绍了React-native桥接Android原生开发详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • ReactNative实现图片上传功能的示例代码

    ReactNative实现图片上传功能的示例代码

    本篇文章主要介绍了ReactNative实现图片上传功能的示例代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-07-07
  • React Native 混合开发多入口加载方式详解

    React Native 混合开发多入口加载方式详解

    这篇文章主要介绍了React Native 混合开发多入口加载方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • React组件的生命周期详解

    React组件的生命周期详解

    React是用于构建用户界面的JavaScript库。本文详细讲解了React的生命周期,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • react 父子组件之间通讯props

    react 父子组件之间通讯props

    这篇文章主要介绍了react 父子组件之间通讯props,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • React函数组件useContext useReducer自定义hooks

    React函数组件useContext useReducer自定义hooks

    这篇文章主要为大家介绍了React函数组件useContext useReducer自定义hooks示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • React+echarts (echarts-for-react) 实现中国地图及省份切换功能

    React+echarts (echarts-for-react) 实现中国地图及省份切换功能

    这篇文章主要介绍了React+echarts (echarts-for-react) 画中国地图及省份切换,有足够的地图数据,可以点击到街道,示例我只出到市级,本文结合实例代码给大家介绍的非常详细需要的朋友可以参考下
    2022-11-11
  • 详解react-router4 异步加载路由两种方法

    详解react-router4 异步加载路由两种方法

    本篇文章主要介绍了详解react-router4 异步加载路由两种方法 ,具有一定的参考价值,有兴趣的可以了解一下
    2017-09-09
  • React项目打包发布到Tomcat页面空白问题及解决

    React项目打包发布到Tomcat页面空白问题及解决

    这篇文章主要介绍了React项目打包发布到Tomcat页面空白问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • webpack+react+antd脚手架优化的方法

    webpack+react+antd脚手架优化的方法

    本篇文章主要介绍了webpack+react+antd脚手架优化的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-04-04

最新评论