ReactHooks+ReactDnd實現拖動數據加載

拖動加載API字段

實現通過鼠標拖拽一個後臺API到Form實現自動加載API所以的字段成表單
拖動組件採用react-dnd這個插件,數據交互和頁面更新等等使用Hooks實現
Hooks官方文檔https://react.docschina.org/docs/hooks-intro.html
ReactDnd官方文檔http://react-dnd.github.io/react-dnd/

實現流程

數據源

http://jianjiacheng.com/json/swagger.json

項目結構

實現流程

效果圖

Demo源碼

https://github.com/jianjiachenghub/ReactHooksDnD.git

拖動加載組件封裝DragBox

組件需要使用useDrag這個dnd插件封裝好的hook
然後將hook返回的函數賦值給DOM的ref屬性進行操作
Items 是拖拽數據的表現形式,用 Object 來表示。

import React from 'react'
import { useDrag } from 'react-dnd'
import { Menu, Icon ,Button} from 'antd';
const DragBox = ({ name, data }) => {
    const [{ opacity }, drager] = useDrag({
        item: { name, type:'dragBox',data},
        collect: monitor => ({
            opacity: monitor.isDragging() ? 0.4 : 1,
        }),
    })
    return (
       <div ref={ drager }><Button value="large" type="dashed" block>{name}</Button></div>
    )
}
export default DragBox

接受拖動的組件Dustbin

accept屬性指定只能接受拖動的item裏type爲dragBox的
drop是一個監聽滑動完成的一個回調

import React from 'react'
import { useDrop } from 'react-dnd'
import CreactForm from "./CreactForm"
const style = {
    minHeight: 780,
    height: '100%',
    border: '1px dashed black'
}
const Dustbin = ({onDrop,data}) => {
    const [{ isOver, canDrop }, drop] = useDrop({
        accept: 'dragBox',
        drop: onDrop,
        collect: monitor => ({
            isOver: monitor.isOver(),
            canDrop: monitor.canDrop(),
        }),
    })


    const getForm = (data)=>{
        if (Object.keys(data).length !== 0) {
            const {data:{properties}} = data
            return <CreactForm data={properties}/>
        }
    }
    return (
        <div ref={drop} style={{ ...style}}>
            {getForm(data)}
        </div>
    )
}
export default Dustbin

界面的展示組件DndMenu

在這個數據的JS代碼部分解析好數據並傳遞給子組件

       <Layout>
           <Sider>
               {returnData.map(({ name, data }, index) => (
                   <DragBox
                       name={name}
                       data={data}
                       key={index}
                   />
               ))}
           </Sider>
           <Content>
               <Dustbin
                   onDrop={item => handleDrop(item)}
                   data={dropData}
               />
           </Content>
       </Layout>

啓用DND需要放到DndProvider中


import React from 'react'
import ReactDOM from 'react-dom'
import DndMenu from './menu'
import { DndProvider } from 'react-dnd'
import HTML5Backend from 'react-dnd-html5-backend'

function Dnd() {
    return (
        <div className="App">
            <DndProvider backend={HTML5Backend}>
                <DndMenu />
            </DndProvider>
        </div>
    )
}
export default Dnd

HOOKS組件注意的問題

useEffect()請求數據的邏輯

  • useEffect() 可以讓你在函數組件中執行副作用操作
  • 默認情況下,它在第一次渲染之後和每次更新之後都會執行。
  • 但是我們不需要在更新的時候再次產生副作用
  • 第二個參數來告訴react只有當這個參數的值發生改變時,才執行我們傳的副作用函數
  • 可以在effect的第二個參數帶個空數組表示不監聽任何值的改變來執行副作用
    useEffect(() => {
        getData()
    },[]);
  • 這裏採用await解析出axios返回的數據然後調用更新函數


    const getData = async () => {
        const result = await axios(
            `${GLOBAL_URL}/list`
        );
        console.log(result)
        const data = result.data[0]
        const api = getKey(data.apiPath)
        getTreeData(api,data.apiPath)
        const originalData = getOriginalData(data.apiPath,data.apiDefinitions)
        setData(originalData)
    }
    
    const [returnData, setData] = useState([]);//根據returnData去渲染UI

函數式組件間的數據交流

以前使用Class語法時在子組件內部使用this.props可以拿到父組件傳遞的數據
而現在的函數式語法可以直接在子組件的參數使用解構賦值拿到上層傳遞的數據

const DragBox = ({ name, data }) => {
}


function DndMenu(props) {
    return (
        <DragBox
           name={name}
           data={data}
           key={index}
        />
    )
}

hooks組件怎麼使用AntDesign的表單函數

以前的Class語法在組件內部想要調用Ant裏面Form的函數只需要類修飾器@後
就能在組件內部使用this.props調用到form的API

@Form.create()
@connect(({ usersModal, basicdata, loading }) => ({
  usersModal,
  basicdata,
  loading : loading.models.usersModal,
  loadingEditFlag : loading.effects['usersModal/saveEditFlag'],
  loadingUpdate : loading.effects['usersModal/UpdateUser'],
  loadingGet : loading.effects['usersModal/getUser'],
  loadingAdd : loading.effects['usersModal/addUser'],
}))
class UserDetail extends PureComponent {
}

現在則可以再導出組件的時候直接將組件傳入Form.create()返回的函數

export default Form.create()(DndMenu)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章