react實現todolist的增刪改查詳解
阿新 • • 發佈:2021-12-27
目錄
- 以todolist為例
- 目錄如下
- app.
- Input.js
- List.js
- Item.js
- Total.js
- Mask.js(彈窗)
- bus.js
- App.
- 總結
以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,{ id: 5,],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,()=>{ 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 { lihttp://www.cppcns.comst } = 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.addHwww.cppcns.comandler}>新增</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: 0http://www.cppcns.com 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.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;
}
總結
本篇文章就到這裡了,希望能夠給你帶來幫助,也希望您能夠多多關注我們的更多內容!