工具实例|react+react-beautiful-dnd实例代办事项

react+react-beautiful-dnd应用 效果预览 【工具实例|react+react-beautiful-dnd实例代办事项】工具实例|react+react-beautiful-dnd实例代办事项
文章图片

实现思路 index.js入口文件配置

import React from 'react' import ReactDOM from 'react-dom' import App from './App' import 'bulma-start/css/main.css' // 引入bulma样式 ReactDOM.render( , document.getElementById('root') )

app.jsx主页面配置
  • Provider格式
return(自己的代码 )

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:'待办事项'+index++, completed: Math.random()>0.5, })) } // 拖拽后的更新state处理函数 drag(newTodos){ this.setState({ todos:[...newTodos], })} // 添加事件处理函数 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, } ] })} // 删除事件处理函数 delTodo=id=>{ this.setState({ todos:this.state.todos.filter(todo=>todo.id !==id) }) } // 更改事件状态处理函数 changComple=id=>{ this.setState({ todos:this.state.todos.map(todo=>{ if(todo.id === id){ todo.completed=!todo.completed } return todo }) })} // 根据总选框状态设置每个单选框状态 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(
) } }

untils/with-context.js封装工具todoContext
import {createContext} from "react"; // 创建creatContext对象 const TodoContext = createContext() // 结构要用到的React组件 const { Provider, // 生产组件 Consumer, // 消费组件 } = TodoContext export { Provider, Consumer, TodoContext, }

  • components/TodoHeader.jsx页面头部
import React, { Component } from 'react'export default class TodoHeader extends Component { render() { return (待办事项列表
) } }

components/TodoInput.jsx该文件主要负责添加事件
import React, {Component, createRef} from "react"; export default class TodoInput extends Component{ state={ inputValue:'输入代办事件', // 定义input输入框内容 } inputRef=createRef() // 定义ref绑定DOM元素,作用是为下面自动获取焦点做准备 // 输入框中输入的内容设置给state作用1:输入框内容改变2:后面提交添加事件拿到input内容 handleChang=Event=>{ this.setState({ inputValue:Event.target.value }) } // 添加代办事件 handleDown=Event=>{ // 验证下是否为空 if(this.state.inputValuehttps://www.it610.com/article/==='' || this.state.inputValue=https://www.it610.com/article/==null) return if(Event.keyCode ===13){ this.add() } } // 添加处理函数 add=()=>{ // add方法通过props从App传入 this.props.add(this.state.inputValue) this.state.inputValue='' // ref绑定后通过inputRef.current拿到DOM元素 this.inputRef.current.focus() } render() { return(

) } }

介绍下react-beautiful-dnd处理函数
  • 官方解析图
    工具实例|react+react-beautiful-dnd实例代办事项
    文章图片
  • 格式DragDropContext最外面盒子Droppable第二层盒子
{provided=>( <* ref={provided.innerRef} {...provided.droppableProps} // 官方固定格式 > 自己的代码 <*/> {provided.placeholder} )}

  • 格式Draggable最里面盒子
{provided=>( <* {...provided.draggableProps} {...provided.dragHandleProps} ref={provided.innerRef} > 自己的代码 <*/> {provided.placeholder} )}

  • 一但移动(从第5个事件移动到第4个事件)onDragEnd回调函数打印结果console.log(result)
{draggableId: '5', type: 'DEFAULT', source: {…}, reason: 'DROP', mode: 'FLUID', …} combine: null destination: {droppableId: 'columns', index: 4} // 移动到第4个事件 draggableId: "5" mode: "FLUID" reason: "DROP" source: {index: 5, droppableId: 'columns'} // 移动的第5个事件 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{ // 类型检查 static propTypes={ todos:PropTypes.array.isRequired, } // 默认值 static defaultProps = { todos: [], } // 根据choice数值决定渲染事项 state={ choice:1 } // react-beautiful-dnd核心处理函数,负责交换后的处理(可以自定义) onDragEnd=result=>{ console.log(result) const {destination,source,draggableId}=result if(!destination){ // 移动到了视图之外 return } if( // 移动到原来位置,也就是位置不变 destination.droppableId===source.droppableId && destination.index===source.index ){ return; } const newTaskIds=Array.from(this.props.todos) // 转化为真正的数组 newTaskIds.splice(source.index,1) // 删除移动的数组 newTaskIds.splice(destination.index,0,this.props.todos[source.index]) // 在移动到的位置初放置被删除的数组// 调用App文件中的drag执行交换后的更改 this.props.drag(newTaskIds)} // 点击时渲染不同DOM choice=(num)=>{ this.setState({ choice:num }) } render() { let uls=null if(this.state.choice===1){ uls=( {provided=>(
    {this.props.todos.length>0 ? this.props.todos.map((todo,index)=>{ return ( ) }) :
    添加代办事项
    } {provided.placeholder}
)}
) }else if(this.state.choice===2){ // 过滤下事件 let newtodos=this.props.todos.filter(todo=> todo.completed) uls=( {provided=>(
    {newtodos.length>0 ? newtodos.map((todo,index)=>{ return ( ) }) :
    暂无已完成事件
    } {provided.placeholder}
)}
) }else if(this.state.choice===3){ // 过滤下事件 let newtodos=this.props.todos.filter(todo=> !todo.completed) uls=( {provided=>(
    {newtodos.length>0 ? newtodos.map((todo,index)=>{ return ( ) }) :
    暂无未完成事件
    } {provided.placeholder}
)}
) } return( <>this.choice(1)}>所有 this.choice(2)}>已完成 this.choice(3)}>未完成
{uls} ) } }

components/TodoFoot.jsx
  • Consumer格式
return( {value=>{ const {结构要用的属性或方法的名字} = value return( 自己的代码,value中含有Provider中传入的所有值 ) }} )

import React,{Component} from "react"; import {Consumer} from '../untils/with-context' export default class TodoFoot extends Component{ render() { return( { 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(
) } }
) } }

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" ] } }

    推荐阅读