zoukankan      html  css  js  c++  java
  • react拖拽案例

    自己随手写了一个小案例,记录一下。

    1、实现右边盒子内容拖到左边盒子里。

    依赖 -- -- 

    react-dnd 
    react-dnd-html5-backend
     
    2、实现左边盒子资源的拖动
    依赖 -- -- 
    react-beautiful-dnd
     
    (1) ---- index.js
    import React, { Component } from "react";
    import { DndProvider } from 'react-dnd'
    import { HTML5Backend } from 'react-dnd-html5-backend'
    import Dustbin from "./Dustbin";
    import Box from "./Box";
    import "./index.less";
    
    class Home extends Component {
      state = {
        mainList: [
          {id: 'item-6', content: 'aaaaaaaaa'},
          {id: 'item-7', content: 'bbbbbbbbb'},
          {id: 'item-8', content: 'ccccccccc'},
          {id: 'item-9', content: 'ddddddddd'},
          {id: 'item-10', content: 'eeeeeeeee'},
          {id: 'item-11', content: 'fffffffff'},
        ],
        sideList: [
          { id: "item-0", content: "hello" },
          { id: "item-1", content: "I" },
          { id: "item-2", content: "am" },
          { id: "item-3", content: "卡" },
          { id: "item-4", content: "特" },
          { id: "item-5", content: "洛" },
        ]
      }
    
      endPull = (opt) => {
        const sideList = [...this.state.sideList, opt];
        // alert('添加成功')
        this.setState({ sideList })
      }
    
      reOrder = (list, startIndex, endIndex) => {
        const result = Array.from(list);
        const [removed] = result.splice(startIndex, 1);
        result.splice(endIndex, 0, removed);
        return result;
      };
    
      onDragEnd = (result) => {
        console.log(result)
        if (!result.destination) return;
    
        const sideList = this.reOrder(
          this.state.sideList,
          result.source.index,
          result.destination.index
        );
        this.setState({ sideList })
      };
    
      render() {
        return (
          <div style={{ paddingLeft: 200, paddingTop: 50, display: 'flex' }} className='page-home'>
           <DndProvider backend={HTML5Backend}>
            <div>
              <Dustbin sideList={this.state.sideList} switchSeat= {sideList => this.setState({ sideList })} />
            </div>
    
            <div style={{flex: 1, display: 'flex', flexWrap: 'wrap'}}>
              {/* 案例实现的是循环里数据都能实现拖拽,所以要循环组件 */}
              {
                this.state.mainList.map(item => {
                  return (
                    <Box
                      key={item.id} 
                      item={item}
                      endPull={this.endPull}
                    />
                  )
                })
              }
            </div>
           </DndProvider>
          </div>
        );
      }
    }
    
    export default Home
    

      

    (2) -- -- Box.index

    import React from "react";
    import { DragSource } from "react-dnd";
    let endPull = null;
    
    const boxSource = {
      /**
       * 开始拖拽时触发当前函数
       * @param {*} props 组件的 props
       */
      beginDrag(props) {
        // 返回的对象可以在 monitor.getItem() 中获取到
        return {
          // name: props.name,
        };
      },
    
      /**
       * 拖拽结束时触发当前函数
       * @param {*} props 当前组件的 props
       * @param {*} monitor DragSourceMonitor 对象
       */
      endDrag(props, monitor) {
        // 当前拖拽的 item 组件
        // const item = monitor.getItem();
        // 拖拽元素放下时,drop 结果
        const dropResult = monitor.getDropResult();
        // 如果 drop 结果存在,就弹出 alert 提示
        if (dropResult) {
          // alert(`You dropped ${item.name} into ${dropResult.name}!`);
          if(!endPull) return;
          endPull(props.item);
        }
      },
    };
    
    @DragSource(
      // type 标识,这里是字符串 'box'
      // ItemTypes.BOX,
      'box',
      // 拖拽事件对象
      boxSource,
      // 收集功能函数,包含 connect 和 monitor 参数
      // connect 里面的函数用来将 DOM 节点与 react-dnd 的 backend 建立联系
      (connect, monitor) => ({
        // 包裹住 DOM 节点,使其可以进行拖拽操作
        connectDragSource: connect.dragSource(),
        // 是否处于拖拽状态
        isDragging: monitor.isDragging(),
      })
    )
    
    class Box extends React.Component {
      componentDidMount() {
        endPull = this.props.endPull;
      }
    
      render() {
        const { connectDragSource } = this.props;
        const { item } = this.props;
        // 使用 connectDragSource 包裹住 DOM 节点,使其可以接受各种拖动 API, connectDragSource 包裹住的 DOM 节点才可以被拖动
    
        return (
          <div style={{display: 'flex'}}>
            {
              connectDragSource &&
              connectDragSource(
                <div key={item.key} style={{ '200px', margin: '50px'}}>
                  <dl style={{ '200px', height: '100px'}}>
                    <dt style={{height: '70px', background: 'pink'}}>图片</dt>
                    <dd style={{height: '30px', background: '#eee'}}>{item.content}</dd>
                  </dl>
                </div>
              )
            }
          </div>
        );
      }
    }
    
    export default Box;
    

      

    (3) -- -- Dustbin.js

    import React from "react";
    import { DropTarget } from "react-dnd";
    import { Collapse } from "antd";
    import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
    
    const { Panel } = Collapse;
    
    const boxTarget = {
      // 当有对应的 drag source 放在当前组件区域时,会返回一个对象,可以在 monitor.getDropResult() 中获取到
      drop: () => ({ name: "Dustbin" }),
    };
    
    @DropTarget(
      // type 标识,这里是字符串 'box'
      // ItemTypes.BOX,
      "box",
      // 接收拖拽的事件对象
      boxTarget,
      // 收集功能函数,包含 connect 和 monitor 参数
      // connect 里面的函数用来将 DOM 节点与 react-dnd 的 backend 建立联系
      (connect, monitor) => ({
        // 包裹住 DOM 节点,使其可以接收对应的拖拽组件
        connectDropTarget: connect.dropTarget(),
        // drag source是否在 drop target 区域
        isOver: monitor.isOver(),
        // 是否可以被放置
        canDrop: monitor.canDrop(),
      })
    )
    class Dustbin extends React.Component {
      state = {
        keyActive: "1",
        periodList: [
          { id: 1, name: "测试1" },
          { id: 2, name: "测试2" },
          { id: 3, name: "测试3" },
        ],
      };
    
      onCollapseChange = (key) => {
        if (key) {
          this.setState({ keyActive: key });
        }
      };
    
      reOrder = (list, startIndex, endIndex) => {
        const result = Array.from(list);
        const [removed] = result.splice(startIndex, 1);
        result.splice(endIndex, 0, removed);
        return result;
      };
    
      onDragEnd = (result) => {
        console.log(result);
        if (!result.destination) return;
    
        const sideList = this.reOrder(
          this.props.sideList,
          result.source.index,
          result.destination.index
        );
    
        this.props.switchSeat(sideList);
      };
    
      render() {
        const { connectDropTarget } = this.props;
        const { sideList } = this.props;
        const { keyActive, periodList } = this.state;
    
        return (
          <div
            style={{  "200px", border: "1px solid gray", height: "500px" }}
          >
            <Collapse
              accordion
              ghost
              className="collapse_wrap"
              // activeKey={1}
              activeKey={keyActive}
              onChange={this.onCollapseChange}
            >
              {periodList &&
                periodList.map((item, index) => {
                  return (
                    <Panel header={item.name} key={item.id} showArrow={false}>
                      <React.Fragment>
                        {connectDropTarget &&
                          connectDropTarget(
                            <div>
                              <DragDropContext
                                onDragEnd={this.onDragEnd}
                              >
                                <Droppable droppableId="droppable">
                                  {(provided) => (
                                    <div
                                      ref={provided.innerRef}
                                      {...provided.droppableProps}
                                    >
                                      {sideList.map((item, index) => (
                                        <Draggable
                                          // 这个key值必须是string类型, 不能是number, 想知道为什么,自己试下就知道了。
                                          key={item.id}
                                          draggableId={item.id}
                                          index={index}
                                        >
                                          {(provided) => (
                                            <div
                                              ref={provided.innerRef}
                                              {...provided.draggableProps}
                                              {...provided.dragHandleProps}
                                            >
                                              <span
                                                style={{
                                                  display: "block",
                                                  height: "30px",
                                                  lineHeight: "30px",
                                                  borderBottom: "1px solid red",
                                                  paddingLeft: "10px",
                                                }}
                                              >
                                                {item.content}
                                              </span>
                                            </div>
                                          )}
                                        </Draggable>
                                      ))}
                                      {provided.placeholder}
                                    </div>
                                  )}
                                </Droppable>
                              </DragDropContext>
                            </div>
                          )}
                      </React.Fragment>
    
                      {/* {
                        connectDropTarget &&
                        connectDropTarget(
                          <div className='class_hour_list'>
                            {
                              detailList.map(v => {
                                return (
                                  <p key={v}>{v.name}</p>
                                )
                              })
                            }
                          </div>
                        )
                      } */}
                    </Panel>
                  );
                })}
            </Collapse>
          </div>
        );
      }
    }
    
    export default Dustbin;
    

      

  • 相关阅读:
    关于求 p_i != i and p_i != i+1 的方案数的思考过程
    poj 3041 Asteroids 二分图最小覆盖点
    poj 1325 Machine Schedule 最小顶点覆盖
    poj 1011 Sticks 减枝搜索
    poj 1469 COURSES 最大匹配
    zoj 1516 Uncle Tom's Inherited Land 最大独立边集合(最大匹配)
    Path Cover (路径覆盖)
    hdu 3530 SubSequence TwoPoint单调队列维护最值
    zoj 1654 Place the Rebots 最大独立集转换成二分图最大独立边(最大匹配)
    poj 1466 Girls and Boys 二分图最大独立子集
  • 原文地址:https://www.cnblogs.com/yetiezhu/p/14807623.html
Copyright © 2011-2022 走看看