網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
react+react-beautiful-dnd實(shí)現(xiàn)代辦事項(xiàng)思路詳解_React
作者:鵬程933 ? 更新時(shí)間: 2022-08-05 編程語(yǔ)言react+react-beautiful-dnd應(yīng)用
效果預(yù)覽
實(shí)現(xiàn)思路
index.js入口文件配置
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import 'bulma-start/css/main.css' // 引入bulma樣式
ReactDOM.render(
<App/>,
document.getElementById('root')
)
app.jsx主頁(yè)面配置
Provider格式
return(
<Provider value={{
'要在tree傳遞的名字':this.'具體屬性或方法'
}}>
自己的代碼
</Provider>
)
import React,{ Component} from "react";
import TodoHeader from './components/TodoHeader.jsx'
import TodoInput from "./components/TodoInput";
import TodoList from "./components/TodoList";
import TodoFoot from "./components/TodoFoot";
import {Provider} from "./untils/with-context" // 引入TodoContext組件
export default class App extends Component{
state ={
todos:Array(6).fill(null).map((_,index)=>({
id:index++,
title:'待辦事項(xiàng)'+index++,
completed: Math.random()>0.5,
}))
}
// 拖拽后的更新state處理函數(shù)
drag(newTodos){
this.setState({
todos:[...newTodos],
})
}
// 添加事件處理函數(shù)
addTodoItem=title=>{
this.setState({
todos:[
...this.state.todos,
{
/* id:this.state.todos[this.state.todos.length-1]+1,
* 更新setState是異步的,這里是拿不到最新的state
*/
id:Math.random(),
title,
completed:false,
}
]
})
}
// 刪除事件處理函數(shù)
delTodo=id=>{
this.setState({
todos:this.state.todos.filter(todo=>todo.id !==id)
})
}
// 更改事件狀態(tài)處理函數(shù)
changComple=id=>{
this.setState({
todos:this.state.todos.map(todo=>{
if(todo.id === id){
todo.completed=!todo.completed
}
return todo
})
})
}
// 根據(jù)總選框狀態(tài)設(shè)置每個(gè)單選框狀態(tài)
allCheckbox=(status)=>{
this.setState({
todos:this.state.todos.map(todo=>{
todo.completed=status
return todo
})
})
}
// 刪除已完成事件
delCompelted=()=>{
this.setState({
todos:this.state.todos.filter(todo=>!todo.completed)
})
}
render() {
return(
<Provider value={{
todos:this.state.todos,
changComple:this.changComple,
delTodo:this.delTodo,
allCheckbox:this.allCheckbox,
delCompelted:this.delCompelted,
}}>
<article className="panel is-success">
<TodoHeader/>
<TodoInput add={this.addTodoItem}/>
<TodoList todos={this.state.todos} drag={this.drag.bind(this)}/>
<TodoFoot/>
</article>
</Provider>
)
}
}
untils/with-context.js封裝工具todoContext
import {createContext} from "react";
// 創(chuàng)建creatContext對(duì)象
const TodoContext = createContext()
// 結(jié)構(gòu)要用到的React組件
const {
Provider, // 生產(chǎn)組件
Consumer, // 消費(fèi)組件
} = TodoContext
export {
Provider,
Consumer,
TodoContext,
}
components/TodoHeader.jsx頁(yè)面頭部
import React, { Component } from 'react'
export default class TodoHeader extends Component {
render() {
return (
<p className="panel-heading">
待辦事項(xiàng)列表
</p>
)
}
}
components/TodoInput.jsx該文件主要負(fù)責(zé)添加事件
import React, {Component, createRef} from "react";
export default class TodoInput extends Component{
state={
inputValue:'輸入代辦事件', // 定義input輸入框內(nèi)容
}
inputRef=createRef() // 定義ref綁定DOM元素,作用是為下面自動(dòng)獲取焦點(diǎn)做準(zhǔn)備
// 輸入框中輸入的內(nèi)容設(shè)置給state作用1:輸入框內(nèi)容改變2:后面提交添加事件拿到input內(nèi)容
handleChang=Event=>{
this.setState({
inputValue:Event.target.value
})
}
// 添加代辦事件
handleDown=Event=>{
// 驗(yàn)證下是否為空
if(this.state.inputValue==='' || this.state.inputValue===null) return
if(Event.keyCode ===13){
this.add()
}
}
// 添加處理函數(shù)
add=()=>{
// add方法通過(guò)props從App傳入
this.props.add(this.state.inputValue)
this.state.inputValue=''
// ref綁定后通過(guò)inputRef.current拿到DOM元素
this.inputRef.current.focus()
}
render() {
return(
<div className="panel-block">
<p className="control has-icons-left">
<input
className="input is-success"
type="text"
placeholder="輸入代辦事項(xiàng)"
value={this.state.inputValue}
onChange={this.handleChang}
onKeyDown={this.handleDown.bind(this)} //該變this指向
ref={this.inputRef}
/>
</p>
</div>
)
}
}
介紹下react-beautiful-dnd處理函數(shù)
官方解析圖
格式DragDropContext最外面盒子Droppable第二層盒子
<DragDropContext onDragEnd={this.onDragEnd}>
<Droppable droppableId='columns'>
{provided=>(
<*
ref={provided.innerRef}
{...provided.droppableProps}
// 官方固定格式
>
自己的代碼
<*/>
{provided.placeholder}
)}
</Droppable>
</DragDropContext>
格式Draggable最里面盒子
<Draggable draggableId={String(id)} index={this.props.index}>
{provided=>(
<*
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={provided.innerRef}
>
自己的代碼
<*/>
{provided.placeholder}
)}
</Draggable>
一但移動(dòng)(從第5個(gè)事件移動(dòng)到第4個(gè)事件)onDragEnd回調(diào)函數(shù)打印結(jié)果console.log(result)
{draggableId: '5', type: 'DEFAULT', source: {…}, reason: 'DROP', mode: 'FLUID', …}
combine: null
destination: {droppableId: 'columns', index: 4} // 移動(dòng)到第4個(gè)事件
draggableId: "5"
mode: "FLUID"
reason: "DROP"
source: {index: 5, droppableId: 'columns'} // 移動(dòng)的第5個(gè)事件
type: "DEFAULT"
[[Prototype]]: Object
components/TodoList.jsx
import React,{Component} from "react";
import TodoItem from "./TodoItem";
import PropTypes from 'prop-types'
import {DragDropContext} from 'react-beautiful-dnd'
import {Droppable} from 'react-beautiful-dnd'
export default class TodoList extends Component{
// 類(lèi)型檢查
static propTypes={
todos:PropTypes.array.isRequired,
}
// 默認(rèn)值
static defaultProps = {
todos: [],
}
// 根據(jù)choice數(shù)值決定渲染事項(xiàng)
state={
choice:1
}
// react-beautiful-dnd核心處理函數(shù),負(fù)責(zé)交換后的處理(可以自定義)
onDragEnd=result=>{
console.log(result)
const {destination,source,draggableId}=result
if(!destination){ // 移動(dòng)到了視圖之外
return
}
if( // 移動(dòng)到原來(lái)位置,也就是位置不變
destination.droppableId===source.droppableId &&
destination.index===source.index
){ return;}
const newTaskIds=Array.from(this.props.todos) // 轉(zhuǎn)化為真正的數(shù)組
newTaskIds.splice(source.index,1) // 刪除移動(dòng)的數(shù)組
newTaskIds.splice(destination.index,0,this.props.todos[source.index]) // 在移動(dòng)到的位置初放置被刪除的數(shù)組
// 調(diào)用App文件中的drag執(zhí)行交換后的更改
this.props.drag(newTaskIds)
}
// 點(diǎn)擊時(shí)渲染不同DOM
choice=(num)=>{
this.setState({
choice:num
})
}
render() {
let uls=null
if(this.state.choice===1){
uls=(<DragDropContext onDragEnd={this.onDragEnd}>
<Droppable droppableId='columns'>
{provided=>(
<ul
ref={provided.innerRef}
{...provided.droppableProps}
>
{this.props.todos.length>0
? this.props.todos.map((todo,index)=>{
return (
<TodoItem key={todo.id} todo={todo} index={index}/>
)
})
:<div>添加代辦事項(xiàng)</div>
}
{provided.placeholder}
</ul>
)}
</Droppable>
</DragDropContext>)
}else if(this.state.choice===2){
// 過(guò)濾下事件
let newtodos=this.props.todos.filter(todo=> todo.completed)
uls=(<DragDropContext onDragEnd={this.onDragEnd}>
<Droppable droppableId='columns'>
{provided=>(
<ul
ref={provided.innerRef}
{...provided.droppableProps}
>
{newtodos.length>0
? newtodos.map((todo,index)=>{
return (
<TodoItem key={todo.id} todo={todo} index={index}/>
)
})
:<div>暫無(wú)已完成事件</div>
}
{provided.placeholder}
</ul>
)}
</Droppable>
</DragDropContext>)
}else if(this.state.choice===3){
// 過(guò)濾下事件
let newtodos=this.props.todos.filter(todo=> !todo.completed)
uls=(<DragDropContext onDragEnd={this.onDragEnd}>
<Droppable droppableId='columns'>
{provided=>(
<ul
ref={provided.innerRef}
{...provided.droppableProps}
>
{newtodos.length>0
? newtodos.map((todo,index)=>{
return (
<TodoItem key={todo.id} todo={todo} index={index}/>
)
})
:<div>暫無(wú)未完成事件</div>
}
{provided.placeholder}
</ul>
)}
</Droppable>
</DragDropContext>)
}
return(
<>
<p className="panel-tabs">
<a className="is-active" onClick={()=>this.choice(1)}>所有</a>
<a onClick={()=>this.choice(2)}>已完成</a>
<a onClick={()=>this.choice(3)}>未完成</a>
</p>
{uls}
</>
)
}
}
components/TodoFoot.jsx Consumer格式
return(
<Consumer>
{value=>{
const {結(jié)構(gòu)要用的屬性或方法的名字} = value
return(
自己的代碼,value中含有Provider中傳入的所有值
)
}}
</Consumer>
)
import React,{Component} from "react";
import {Consumer} from '../untils/with-context'
export default class TodoFoot extends Component{
render() {
return(
<Consumer>
{
value => {
const {allCheckbox,todos,delCompelted} = value
const completedNum =todos.filter(todo=>todo.completed).length
const AllChecked =todos.length?todos.every(todo=>todo.completed):false
return(
<div>
<label className="panel-block">
<input type="checkbox" checked={AllChecked} onChange={(event)=>allCheckbox(event.target.checked)}/>全選
<span>已完成{completedNum}</span>
<span>一共{todos.length}</span>
</label>
<div className="panel-block">
<button className="button is-success is-outlined is-fullwidth" onClick={delCompelted}>
刪除已完成
</button>
</div>
</div>
)
}
}
</Consumer>
)
}
}
package.json中的三方包資源
{
"name": "react-demo",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"bulma-start": "^0.0.5",
"react": "^17.0.2",
"react-beautiful-dnd": "^13.1.0",
"react-dom": "^17.0.2",
"react-native": "^0.68.2",
"react-scripts": "4.0.3",
"redux-persist": "^6.0.0",
"store": "^2.0.12",
"web-vitals": "^1.0.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
原文鏈接:https://blog.csdn.net/weixin_64925940/article/details/125191059
相關(guān)推薦
- 2022-06-02 ubuntu安裝jupyter并設(shè)置遠(yuǎn)程訪問(wèn)的實(shí)現(xiàn)_python
- 2023-07-30 vscode自定義用戶(hù)代碼片段
- 2023-02-03 Linux設(shè)置每晚定時(shí)備份Oracle數(shù)據(jù)表的操作命令_linux shell
- 2022-12-27 Golang中int,?int8,?int16,?int32,?int64和uint區(qū)別淺析_Gol
- 2022-10-04 一文教會(huì)你用Python讀取PDF文件_python
- 2022-07-21 Linux上源碼包安裝nginx及yum 安裝nginx
- 2022-03-26 C語(yǔ)言關(guān)于時(shí)間復(fù)雜度詳解_C 語(yǔ)言
- 2022-04-19 python獲取http請(qǐng)求響應(yīng)頭headers中的數(shù)據(jù)的示例_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支