• react-dnd例子代码学习记录


    例子代码仓库:react-dnd

    摘出了关键代码,并添加了注释的代码文件

    参考文档:

    一直以来useCallback的使用姿势都不对-普拉斯强(useCallback的用法)

    React Hooks 解析(下):进阶-dabai(useCallback的用法)

    react hooks 之 useCallback ,useMemo-饭饭大人(useCallback的用法)

    React性能优化:immutability-helper-weixin_34216196(immutability-helper的用法)

    [转] immutability-helper 插件的基本使用(附源码)-{前端开发}(immutability-helper的用法)

    react-dnd拖拽页面记录-对鸭(将react-dnd用法分四部分)

    用 React Hooks 的方式使用 react-dnd-暖生(通过例子讲react-dnd用法)

    最外层

    index.tsx

    引入了DndProvider[react-dnd]、HTML5Backend[react-dnd-html5-backend]

    import React from 'react'
    import ReactDOM from 'react-dom'
    import { Container } from './Container'
    import { DndProvider } from 'react-dnd'
    import { HTML5Backend } from 'react-dnd-html5-backend'
    
    function App() {
    	return (
    		<div className="App">
    			<DndProvider backend={HTML5Backend}>
    				<Container />
    			</DndProvider>
    		</div>
    	)
    }
    
    const rootElement = document.getElementById('root')
    ReactDOM.render(<App />, rootElement)
    

    中间层

    Container.tsx

    数据源和数组交换的代码在这里。

    1. 数组交换时使用了useCallback。在依赖不变的情况下,会返回相同的引用,避免子组件进行无意义的重复渲染。useCallback缓存方法的引用。

      useCallback(函数,依赖项)

      const click = useCallback(() => {
      console.log(value)
      }, [value])

      当依赖项发生改变时,该方法会重新创建更新。

      内部的value值会随之更新,否则value永远是初始值

    2. 引入了immutability-helper,以最低的成本对抗浅比较

    immutability-helper用法

    使用示例:

    update(target_array, {score: {$push: [10]}}) // 返回新的对象
    

    注意点:

    $push、$unshift、$splice的使用目标必须是数组。

    $add、$remove的使用目标必须是Set或Map。

    $splice的参数是一个操作数组,可以对目标数组一次进行多次操作,但是参数arrays中的项是按顺序执行的。

    可用命令:

    {$push: array}
    同数组的 push 方法,将参数 array 中的所有项 push 到目标数组中

    {$unshift: array}
    同数组的 unshift 方法,将参数 array 中的所有项 unshift 到目标数组中

    {$splice: array of arrays}
    同数组的 splice 方法,对于参数 arrays 中的每一项,使用该项提供的参数对目标数组调用 splice()

    array.splice(index,howmany,item1,......itemX)
    

    {$set: any}
    使用 any 值替换目标

    {$toggle: array of strings}
    将参数 array 中提供的下标或者属性的值切换成相反的布尔值

    {$unset: array of strings}
    从目标对象中移除参数 array 中的键列表

    {$merge: object}
    将参数 object 的键与目标合并

    {$apply: function}
    将当前值传递给函数并用新的返回值更新它

    {$add: array of objects}
    向 Set 或 Map 中添加值。添加到 Set 时,参数 array 为要添加的对象数组,添加到 Map 时,参数 array 为 [key, value] 数组

    {$remove: array of strings}
    从 Set 或 Map 中移除参数 array 中的键列表

    扩展运算符与immutability-helper比较:

    扩展运算符:

    newState = {
        ...state,
        score: {
            ...state.score,
            exam2: [
                ...state.score.exam2, 
                90,
            ],
        },
    }
    

    使用immutability-helper:

    newState = update(state, {
        score: {
            exam2: {
                $push: [90]
            }
        }
    })
    

    核心层

    Card.tsx

    使用react-dnd的API

    react-dnd用法

    monitor

    一个DragSourceMonitor / DropTargetMonitor实例。

    // DragSourceMonitor
    monitor.canDrag()         // 是否能被拖拽
    monitor.isDragging()      // 是否正在拖拽
    monitor.getItemType()     // 拖拽组件type
    monitor.getItem()         // 当前拖拽的item
    monitor.getDropResult()   // 查询drop结果
    monitor.didDrop()         // source是否已经drop在target
    monitor.getInitialClientOffset()   // 拖拽组件初始拖拽时offset
    monitor.getInitialSourceClientOffset()
    monitor.getClientOffset() // 拖拽组件当前offset
    monitor.getDifferenceFromInitialOffset() // 当前拖拽offset和初始拖拽offset的差别
    monitor.getSourceClientOffset()
    
    // DropTargetMonitor
    monitor.canDrop()         // 是否可被放置
    monitor.isOver(options)   // source是否在target上方
    monitor.getItemType()     // 拖拽组件type
    monitor.getItem()         // 当前拖拽的item
    monitor.getDropResult()   // 查询drop结果
    monitor.didDrop()         // source是否已经drop在target
    monitor.getInitialClientOffset()   // 拖拽组件初始拖拽时offset
    monitor.getInitialSourceClientOffset()
    monitor.getClientOffset() // 拖拽组件当前offset
    monitor.getDifferenceFromInitialOffset() // 当前拖拽offset和初始拖拽offset的差别
    monitor.getSourceClientOffset()
    

    useDrag用于拖动

    const [collect方法返回的对象,ref引用] = useDrag({参数})

    1. 返回值:[collect方法返回的对象,ref引用]

      第一个值是collect方法返回的对象。

      第二个值是ref引用,将其赋值给想要拖拽的元素就可以实现组件拖动。

    2. 参数

    • item是一个对象,必须要有一个type属性(必填)

      item: { type: ItemTypes.CARD, 其他属性 },
      
    • begin(mintor:DragSourceMonitor)组件开始拖动时触发,必须返回一个包含type属性的对象,会覆盖item属性返回的对象,会被传入drop组件hover和drop方法的第一个参数

    • end(item,mintor:DragSourceMonitor)组件停止拖动时触发,item是drop组件在drop方法执行时返回的对象,等同于mintor.getDropResult()的值

    • canDrag指定当前是否允许拖动

    • isDragging默认情况下,只有启动拖动操作的数据源才被认为是拖动

    • collect(mintor:DropTargetMonitor)函数,返回的对象会成为useDrag的第一个参数,可以在组件中直接进行使用

    • spec普通对象

    useDrop用于接收

    const [collect方法返回的对象,ref引用] = useDrop({参数})

    1. 返回值:[collect方法返回的对象,ref引用]

      第一个值是collect方法返回的对象。

      第二个值是ref引用,将其赋值给想要接收drag组件的元素,就可以感应到拖动的元素。

    2. 参数

    • accept是一个标识字符串,需要和对应的drag元素中item的type值一致,否则不能感应

      accept: ItemTypes.CARD
      
    • hover(item,mintor:DropTargetMonitor)drag组件在drop组件上方hover时触发

    • drop(item,mintor:DropTargetMonitor)drag组件拖拽结束后,放到drop组件时触发,返回的值会作为参数传递给drag组件end方法的第一个参数

    • collect(mintor:DropTargetMonitor)函数,返回的对象会成为useDrop的第一个参数,可以在组件中直接进行使用

    • options普通对象

    相关用法

    1. 让组件既可以被拖动也可以接收拖动元素

    (1)使用useRef引入ref:ref = useRef(null)

    (2)使用drag和drop包装ref:drag(drop(ref))

    (3)将ref变量传给组件

    1. drag组件传递数据

    (法1)直接使用item的属性传:item:{type:'Card‘,id:1}

    (法2)使用begin方法传值,begin方法的返回值会覆盖item属性,一定要传type属性

    drop组件可以在hover或drop方法中的第一个参数获取到,或使用DropTartgetMonitor的getItem()函数获取

    1. 获取drag组件或drop组件的状态信息,如isOver,isDragging
    • drag:collect函数返回的对象会成为useDrag的第一个参数collectProps,可以在组件中直接使用
    • drop:collect函数返回的对象会成为useDrop的第一个参数collectProps,可以在组件中直接使用

    文件其他涉及方法

    getBoundingClientRect用于获取某个元素相对于视窗的位置集合

    hover方法中拖动比较

    image-20210203100323859

  • 相关阅读:
    机器学习 深度学习 网站
    Concat层解析
    网络可视化工具netron详细安装流程
    【中文】【deplearning.ai】【吴恩达课后作业目录】
    python 3 linux环境搭建django production环境
    eCharts画图
    mysql 外键
    django执行离线ORM、数据操作
    http 发包调试工具
    python有空仔细研究
  • 原文地址:https://www.cnblogs.com/wattmelon/p/14365469.html
Copyright © 2020-2023  润新知