vue原生开发实现批量拖拽之一

拖拽功能的html部分:表格部分(被拽入)、人员列表(被拽出)、移动时的状态

表格部分(被拽入):这部分数据主要执行一个数据列表渲染。一个hover状态判断是否为被移入的dom。

人员列表(被拽出):1.点击事件,添加/删除选中当天条目。2.mouseDown事件,这是移动过程的初始点。3.out状态:被拖出时的一个特殊显示

移动时的状态:只需要一个显示隐藏,并且在显示的时候跟着鼠标

<div id="main">
    <div id="table" ref="table">
        <ul>
            <li v-for="item in tableData" :class="{hover: item.data.hover}">
                <div v-for="itemIn in item.data.person">{{itemIn.name}}</div>
            </li>
        </ul>
    </div>
    <div id="person" ref="person">
        <ul>
            <li @click="personClickHandler(item)" @mouseDown="personMouseDownHandler($event)" v-for="(item, index) in personData" :class="{active: item.selected, out: item.out}">{{item.name}}</li>
        </ul>
    </div>
    <div id="moveBox" ref="moveBox" v-show="moveBoxShow" >
        <ul>
            <li v-for="item in moveBox">{{item.name}}</li>
        </ul>
    </div>
</div>

js 逻辑部分

  • 数据
  • 方法归类

数据

tableData:控制table中的数据

tableDom:控制table中的大小及当前被移入的序号

personData:控制人员列表。selected是当前被选中,out时选中部分移出时的透明度变化

moveBoxShow:是否显示移动中状态

moveBox:移动中的内容

方法归类

tableData 数据初始化:这里要给table表格填充数据,这里通过计算,将每个cell的坐标也添加了进去,方便以后计算。

personMouseDownHandler 开始移动:1.通过_personToCheckedBox将选中的人员添加到移动数据中。2.通过_checkOutPersonContainer判断是否移出了 person的dom,移出时显示移动状态盒子。3.通过_checkInTableCell判断当前鼠标是否进入了表格中的某一项,进入了就进行标记并获取index。4.鼠标抬起时 需要判断是否已经选中被移入的dom,已选中的话,就对两个列表数据进行修改。对数据进行重置

    var vm = new Vue({
        el: "#main",
        data: {
            tableData: [],
            tableDom: {
                col: 4,
                width: 200,
                height: 50,
                selected: ''
            },
            personData: [
                {
                    name: '小明',
                    selected: false,
                    out: false
                },
                {
                    name: '小红',
                    selected: false,
                    out: false
                },
                {
                    name: '小黑',
                    selected: false,
                    out: false
                },
                {
                    name: '小绿',
                    selected: false,
                    out: false
                },
                {
                    name: '大卖',
                    selected: false,
                    out: false
                },
                {
                    name: '春天',
                    selected: false,
                    out: false
                },
                {
                    name: '夏天',
                    selected: false,
                    out: false
                },
                {
                    name: '秋天',
                    selected: false,
                    out: false
                }
            ],
            // 移动副本是否显示
            moveBoxShow: false,
            // 移动副本数据
            moveBox: []
        },
        created () {
          this._initHandler()
        },
        methods:{
            _initHandler () {
                this._tableDataInit()
            },
            // tableData 数据初始化
            _tableDataInit () {
                let dom = document.getElementById('table')
                let parX = dom.offsetLeft
                let parY = dom.offsetTop
                console.log(parX);
                console.log(parY);
                let arr = []
                for (let i = 0; i < 28; i++) {
                    let obj = {
                        data: {
                            x1: parX + (i % this.tableDom.col) * this.tableDom.width,
                            y1: parY + Math.floor(i / this.tableDom.col) * this.tableDom.height,
                            x2: parX + (i % this.tableDom.col + 1) * this.tableDom.width,
                            y2: parY + Math.floor(i / this.tableDom.col + 1) * this.tableDom.height,
                            hover: false,
                            person: []
                        },
                        idx: i
                    }
                    arr.push(obj)
                }
                this.tableData = arr
            },
            // 点击人
            personClickHandler (item) {
                item.selected = !item.selected
            },
            // 开始移动
            personMouseDownHandler (event) {
                console.log(event);//鼠标按下,计算当前元素距离可视区的距离
                let _this = this
                let oDiv = document.getElementById('moveBox')
                this._personToCheckedBox()
                document.onmousemove = function (event) {
                    // 是否出了人员框,显示副本
                    if (_this._checkOutPersonContainer(event.clientX, event.clientY)) {
                        _this._personShowCopy(event.clientX, event.clientY)
                    }
                    // 是否进入表格中的某一项
                    _this._checkInTableCell(event.clientX, event.clientY)
                };
                document.onmouseup = function (event) {
                    document.onmousemove = null;
                    document.onmouseup = null;
                    if (_this.tableDom.selected) {
                        _this._insertPersonToTable()
                    }
                    _this._resetPersonMove()
                };
            },
            // 判断是否出了person框
            _checkOutPersonContainer (x, y) {
                let dom = document.getElementById('person')
                let domHeight = (dom.currentStyle ? dom.currentStyle : getComputedStyle(dom, null)).height
                let domWidth = (dom.currentStyle ? dom.currentStyle : getComputedStyle(dom, null)).width
                let x2left = dom.offsetLeft
                let x3left = dom.offsetLeft + domWidth
                let x2top = document.getElementById('person').offsetTop
                let x3top = document.getElementById('person').offsetTop + domHeight
                if (x < x2left || x > x3left || y < x2top || y > x3top) {
                    return true
                }
                return false

            },
            // 拖出person框,显示副文件
            _personShowCopy (x, y) {
                this.moveBoxShow = true
                let dom = document.getElementById('moveBox')
                dom.style.left = x + 'px'
                dom.style.top = y + 'px'
                this._personOutOpacity()
            },
            // person框中本选中部分透明度改变
            _personOutOpacity () {
                this.personData.forEach(item => {
                    if (item.selected) {
                        item.out = true
                    }
                })
            },
            // 向person选中数组填充人员
            _personToCheckedBox () {
                let arr = []
                this.personData.forEach(item => {
                    if (item.selected) {
                        arr.push(item)
                    }
                })
                this.moveBox = arr
            },
            // 是否进入表格中的某一项
            _checkInTableCell (x, y) {
                this.tableData.forEach((item, index) => {
                    if (x > item.data.x1 && x < item.data.x2 && y > item.data.y1 && y < item.data.y2) {
                        item.data.hover = true
                        this.tableDom.selected = index
                    } else {
                        item.data.hover = false
                    }
                })
            },
            // 是否需要将人员写入表格
            _insertPersonToTable () {
                this.tableData[this.tableDom.selected].data.person = copyDeep(this.moveBox)
                let arr = []
                this.personData.forEach(item => {
                    if (!item.out) {
                        arr.push(item)
                    }
                })
                this.personData = arr
            },
            // 重置人员移动数据
            _resetPersonMove () {
                if (!this.moveBoxShow) {
                    return
                }
                this.tableDom.selected = ''
                this.personData.forEach(item => {
                    item.selected = false
                    item.out = false
                })
                this.tableData.forEach(item => {
                    item.data.hover = false
                })
                this.moveBoxShow = false
                this.moveBox = []
            }
        }
    });

    function copyDeep(origin) {
        if (origin instanceof Object) {
            if (isArray(origin)) {
                var targetArr = []
                for (var i = 0; i < origin.length; i++) {
                    targetArr.push(copyDeep(origin[i]))
                }
                return targetArr
            } else {
                var targetObj = {}
                for (var item in origin) {
                    targetObj[item] = copyDeep(origin[item])
                }
                return targetObj
            }
        } else {
            return origin
        }
        function isArray(value) {
            return !!value && value instanceof Array
        }
    }

随机浏览