利用HTML5拖放(Drag 和 Drop)實現Table間數據的交互

前言

做爲開發者,咱們老是會不經意間的遇到一些使人頭疼的需求。好比五彩斑斕的黑,根據手機殼變換APP的顏色等等,你說怎麼辦。雖然在通常狀況下不會這麼棘手,可是有些需求剛拿到的時候仍是會束手無策。javascript

表格間數據傳遞

曾經遇到一個相似這樣的需求:A表的數據須要沿用B表中的數據,並且要儘可能少的步驟。具體什麼意思呢,意思就是完成一個相似於下面這種效果:
最終效果圖html

這個該這麼搞,直接給產品說,對不起實現不了。html5

但是產品卻告訴我,不行不行,必須實現。java

沒辦法,只好妥協。react

梳理

OK,咱們來理理思路,首先肯定一下現有的主要開發環境:antd

  • 框架:react
  • UI庫:antd

既然要實現上圖所示的拖放效果,那麼HTML5的拖放一系列API(Drag 和 Drop等)確定就是主角了。原生API以及用法能夠點擊這裏進行摸索。框架

熟悉了API後咱們便要對需求進行分析,明確三個要點:第一是拖放的動做,這個用拖放API就能很好的解決;第二是表格間的數據交互,也就是怎麼把表格B中部分數據(序號)添加到表格A(沿用信息);第三是表格B中每一行的序號與表格A中的沿用信息都是一對多的關係,並且表格A中的沿用信息是便可添加也能夠替換的。this

弄清楚須要解決的要點後,咱們就能夠着手coding了。spa

具體實現

首先,咱們要先創建兩張表格,而且製造假數據:code

import React, { Component } from 'react';
import {Table, Row, Col, Button} from 'antd';

export class App extends Component {
    columnsA
    columnsB
    constructor(props) {
        super(props);
        this.columnA = [
            {
                title: '姓名',
                dataIndex: 'name',
                key: 'name',
            },
            {
                width: 100,
                title: '沿用信息',
                dataIndex: 'obj',
                key: 'obj',
            }
        ]
        this.columnsB = [
            {
                title: '序號',
                dataIndex: 'num',
                key: 'num',
            },
            {
                title: '信息',
                dataIndex: 'info',
                key: 'info',
            }
        ]
        this.state = {
            dataSourceA: [
                {
                    key: '1',
                    name: '小明',
                    obj: ''
                },
                {
                    key: '2',
                    name: '李華',
                    obj: ''
                },
                {
                    key: '3',
                    name: '小花',
                    obj: ''
                }
            ],
            dataSourceB: [
                {
                    key: '1',
                    num: '1',
                    info: '信息一'
                },
                {
                    key: '2',
                    num: '2',
                    info: '信息一'
                },
                {
                    key: '3',
                    num: '3',
                    info: '信息一'
                }
            ]
            
        }
    }

    componentDidMount(){
        
    }

    render(){
        return (
            <div className="content" style={{margin: "20px 20px"}}>
                <Row gutter={24}>
                    <Col span={11}>
                        <Table columns={this.columnsA} dataSource={this.state.dataSourceA} />
                    </Col>
                    <Col span={11}>
                        <Table columns={this.columnsB} dataSource={this.state.dataSourceB} />
                    </Col>
                </Row>
            </div>
        )
    }
}

效果以下:
初始表格

接下來就是實現拖放動做,由於這裏使用了antd的Table組件,因此咱們很天然的就能夠想到在columns作文章,在這裏把原生的拖放API進行拓展。序號是須要拖拽的元素,而沿用信息是須要進行接收的元素。爲了讓拖放更加明顯,因此咱們在這裏也加了一點樣式:

this.columnA = [
    {
        title: '姓名',
        dataIndex: 'name',
        key: 'name',
    },
    {
        width: 100,
        title: '沿用信息',
        dataIndex: 'obj',
        key: 'obj',
        render: (value, row, index) => {
            return <div
                id={'drop'+index}
                style={{height:"30px",width:"30px",border:"1px solid #eee",textAlign: "center",lineHeight: "30px"}}
                onDrop={(e) => {
                    e.preventDefault();
                    this.drop(e)
                }}
                onDragOver={this.allowDrop}
            >{value}</div>
        }
    }
]

this.columnsB = [
    {
        title: '序號',
        dataIndex: 'num',
        key: 'num',
        render: (value, row, index) => {
            return <div 
            draggable="true"
            id={'drag'+value}
            style={{height:"30px",width:"30px",border:"1px solid #eee",textAlign: "center",lineHeight: "30px"}}
            onDragStart={(e) => {
                this.drag(e)
            }}>{value}</div>
        }
    },
    {
        title: '信息',
        dataIndex: 'info',
        key: 'info',
    }
]
drag = (e) => {
    console.log(e)
};

drop = (e) => {
    console.log(e);
};

allowDrop = (e) => {
    e.preventDefault();
};

效果以下:
拖放

拖放動做是有了,可是兩個表格的數據並無發生變化,因此接下來咱們要進行數據的處理。想要進行數據的傳遞,咱們能夠利用拖放API中的:

  1. dataTransfer.setData()方法設置被拖數據的數據類型和值;
  2. dataTransfer.getData()方法得到被拖的數據。該方法將返回在 setData() 方法中設置爲相同類型的任何數據。
// columnsA
{
    width: 100,
    title: '沿用信息',
    dataIndex: 'obj',
    key: 'obj',
    render: (value, row, index) => {
        return <div
            id={'drop'+index}
            style={{height:"30px",width:"30px",border:"1px solid #eee",textAlign: "center",lineHeight: "30px"}}
            onDrop={(e) => {
                e.preventDefault();
                this.drop(e)
            }}
            onDragOver={this.allowDrop}
        >{value}</div>
    }
}

// columnsB
{
    title: '序號',
    dataIndex: 'num',
    key: 'num',
    render: (value, row, index) => {
        return <div
            draggable="true"
            id={'drag'+value}
            style={{height:"30px",width:"30px",border:"1px solid #eee",textAlign: "center",lineHeight: "30px"}}
            onDragStart={(e) => {
                this.drag(e,value)
            }}>{value}</div>
    }
},
drag = (e,value) => {
    console.log(e)
    e.dataTransfer.setData('value', value)
};

drop = (e, key) => {
    let value = e.dataTransfer.getData('value')
    console.log("獲取數據:",value);
};

拖放數據

能夠看到,咱們已經可以獲取到拖拽的數據了。最後咱們要對錶格A的數據進行處理,首先對dataSourceA進行遍歷,若是其中的元素的key和接受數據的元素的key相等的話,那就對此元素的obj字段進行賦值:

// columnsA
{
    width: 100,
    title: '沿用信息',
    dataIndex: 'obj',
    key: 'obj',
    render: (value, row, index) => {
        return <div
            id={'drop'+index}
            style={{height:"30px",width:"30px",border:"1px solid #eee",textAlign: "center",lineHeight: "30px"}}
            onDrop={(e) => {
                e.preventDefault();
                this.drop(e, row.key)
            }}
            onDragOver={this.allowDrop}
        >{value}</div>
    }
}
drop = (e, key) => {
    let value = e.dataTransfer.getData('value')
    console.log("獲取數據:",value);
    let data = this.state.dataSourceA;
    data.forEach((item) => {
        if (item.key == key) {
            item.obj = value
        }
    });
    this.setState({
        dataSourceA: data
    })
};

看看效果:
接收數據

固然咱們也能夠把表格A中的數據打印出來看看:
最終數據

數據真實的發生了改變~~

這個demo基本就算完成了,以上代碼結合起來差很少就是這次demo的完整代碼。

參考

https://www.runoob.com/html/h...

https://developer.mozilla.org...

最後

不少時候遇到的問題,看似有點麻煩,可是隻要去仔分析,而後對問題進行拆解,老是能找到比較好的解決方案的。

文章如有不足或有更好建議,歡迎提出,你們一塊兒討論~

相關文章
相關標籤/搜索