zoukankan      html  css  js  c++  java
  • element table 实现鼠标拖拽选中

    父组件

    <template>
        <div id='add'>
            <airtable
                :tableData="tableData"
                :columData="columData"
                :menuList ="menuList"
                :pageTotal="pageTotal"
                @rowContextmenu="rowContextmenu"
                @currentPageChange="currentPageChange"
                @handleSelect="handleSelect"
            >
                <template slot=date slot-scope="scope">
                    <!--把所有的数据都变成插槽导出-->
                    <div class="air-table-slot__div">{{scope.row.date}}</div>
                </template>
                <template slot=name slot-scope="scope">
                    <!--把所有的数据都变成插槽导出-->
                    <div class="air-table-slot__div">{{scope.row.name}}</div>
                </template>
                <template slot=address slot-scope="scope">
                    <!--把所有的数据都变成插槽导出-->
                    <div class="air-table-slot__div">{{scope.row.address}}</div>
                </template>
            </airtable>
        </div>
    </template>
    <script>
    import airtable from "@/components/newCommon/table/table.vue";
    export default {
        components: {
            airtable
        },
        name: 'text-form',
        data() {
            return {
                columData:[
                    {
                        name: '时间',
                        key: 'date',
                        isFixed: true,//固定列参数
                        "auto"
                    },
                    {
                        name: '名字',
                        key: 'name',
                        isFixed: true,//固定列参数
                        "auto"
                    },
                    {
                        name: '地址',
                        key: 'address',
                        isFixed: true,//固定列参数
                        "auto"
                    },
                ],
                //table 表头字段数据
                tableData: [
                    
                ],
                //这个是右键的按钮操作
                menuList:[{icon:"air-icon-moreapps",name:"操作"},{icon:"air-icon-moreapps",name:"曾加"},{icon:"air-icon-moreapps",name:"修改"}],
                //从后台获得的分页的总数
                pageTotal:100
            }
        },
        methods: {
            //鼠标右键菜单点击事件 传出来的是要做的操作和当前的列
            rowContextmenu(item,row){
                console.log(item,row);
            },
            //监听当前页的变化
            currentPageChange(currentpage){
                console.log(currentpage);
            },
            //当鼠标批量编辑时或者点击鼠标选中时触发 传来的是选中的列表数据
            handleSelect(multipleSelection){
                console.log(multipleSelection)
            }
        },
        watch: {
            
        },
        created(){
            for(var i=0;i<20;i++){
                this.tableData.push({
                    date: '2016-05-03',
                    name: '王小虎',
                    address: '上海市普陀区金沙江路 1518 弄dddddddddddddddddddddddddddd',
                    id:i
                })
            }
        }
    }
    
    </script>
    
    <style>
    #add {
        height:100%;
    }
    .el-carousel__item h3 {
        color: #475669;
        font-size: 18px;
        opacity: 0.75;
        line-height: 300px;
        margin: 0;
    }
    
    .el-carousel__item:nth-child(2n) {
        background-color: #99a9bf;
    }
    
    .el-carousel__item:nth-child(2n + 1) {
        background-color: #d3dce6;
    }
    .mengban {
        position: fixed;
        border: 1px solid rgb(0, 119, 255);
        background-color: rgba(0, 119, 255, 0.3);
        -moz-user-select: none;
        -khtml-user-select: none;
        user-select: none;
    }
    tbody{
        position: relative;
    }
    .air-table-slot__div {
        min- 200px;
        max- 300px;
        overflow: hidden;/*超出部分隐藏*/
        white-space: nowrap;/*不换行*/
        text-overflow:ellipsis;/*超出部分文字以...显示*/
    }
    </style>
    

      子组件table

    <template>
        <div class='air-table-wrapper'>
            <el-table 
                ref="table"
                :show-header="true"
                :data="tableData"
                tooltip-effect="dark"
                style=" 100%;"
                :header-row-class-name="headerClassName"
                :height="'500'"
                id="table" 
                @row-click="rowClick"
                @row-contextmenu="rowContextmenu"
                v-drag>
                <el-table-column  :type="isType" width="55" align="center"></el-table-column>
                <!--列表的表头循环-->
                <el-table-column
                    v-for="(column, index) in columData"
                    :key="index"
                    :label="column.name"
                    :width="column.width">
                    <template slot-scope="scope">
                        <!--把所有的数据都变成插槽导出-->
                        <slot :name="column.key" :row="scope.row"> </slot>
                    </template>
                </el-table-column>
                <template slot=append>
                    <div :class="['el-table__append-page']">
                        <el-pagination
                            @size-change="handleSizeChange"
                            @current-change="handleCurrentChange"
                            :current-page.sync="currentPage"
                            :page-size="20"
                            layout="total, prev, pager, next"
                            :total="pageTotal">
                        </el-pagination>
                    </div>
                </template>
            </el-table>
            <air-contex-menu
                :position="position"
                :toggleShow="toggleShow"
                :menuList="menuList"
                @menuClick="menuClick"
            ></air-contex-menu>
        </div>
    </template>
    <script>
    import airContexMenu from './contextMenu.js';
    export default {
        name: 'airtable',    
        // 框选的指令
        directives: {
            drag: {
                // 指令的定义
                inserted: function (el, binding, vnode) {
                    var oDiv = el;
                    //监听用户鼠标事件
                    oDiv.onmousedown = function (ev) {
                        //初始化不显示
                        vnode.context.toggleShow=false;   
                        //确保用户在移动鼠标的时候只初始化一次选中
                        var flag = true;
                        //用来存储列表
                        var selList = [];
                        //获得指令下的dom对应的表格
                        var fileNodes = oDiv.getElementsByTagName("tr");     
                        var countI = 0;
                        //获得鼠标
                        var evt = window.event || arguments[0];
                        var startX = (evt.x || evt.clientX);
                        var startY = (evt.y || evt.clientY);
                        var top,left;
                        //时时获得
                        top=getY(oDiv);
                        left=getX(oDiv);
                        var selDiv = document.createElement("div");
                        selDiv.style.cssText = "position:absolute;0px;height:0px;font-size:0px;margin:0px;padding:0px;border:1px dashed #0099FF;background-color:#C3D5ED;z-index:1000;filter:alpha(opacity:60);opacity:0.6;display:none;";
                        selDiv.id = "selectDiv";
                        document.getElementsByClassName("el-table__body")[0].appendChild(selDiv);
                        selDiv.style.left = startX + "px";
                        selDiv.style.top = startY + "px";
                        var _x = null;
                        var _y = null;
                        vnode.context.clearEventBubble(evt);
                        // //打开开关
                        vnode.context.mouseflag = true;
                        // //鼠标拖动时画框
                        document.onmousemove = function (ev) {
                            evt = window.event || arguments[0];
                            _x = (evt.x || evt.clientX);
                            _y = (evt.y || evt.clientY);
                            //为了确定是点击事件还是移动事件
                            if(Math.abs(_x - startX)<5 && Math.abs(_y - startY)<5){
                                return;
                            }
                            //为了确保只有一次的渲染每次框选都把默认选中为空
                            if(flag){
                                //重置选中css
                                for (var i = 0; i < fileNodes.length; i++) {
                                    if (fileNodes[i].className.indexOf("el-table__row") != -1) {
                                        fileNodes[i].className = "el-table__row";
                                        selList.push(fileNodes[i]);
                                    }
                                }      
                                vnode.context.multipleSelection=[]
                                vnode.context.tableData.forEach((ele)=>{
                                    vnode.context.$refs.table.toggleRowSelection(ele,false)
                                })
                                flag = false;
                            }
                            if (vnode.context.mouseflag) {
                                if (selDiv.style.display == "none") {
                                    selDiv.style.display = "";
                                }
                                var scrolling=oDiv.getElementsByClassName("is-scrolling-none");
                                selDiv.style.left = Math.min(_x, startX)-left+scrolling[0].scrollLeft + "px";
                                //48是表头的高度
                                selDiv.style.top = Math.min(_y, startY)-top - 48+scrolling[0].scrollTop+ "px";
                                selDiv.style.width = Math.abs(_x - startX) + "px";
                                selDiv.style.height = Math.abs(_y - startY) + "px";
    
                                // ---------------- 关键算法确定列表的选中靠的是index---------------------
                                var _l = selDiv.offsetLeft, _t = selDiv.offsetTop;
                                var _w = selDiv.offsetWidth, _h = selDiv.offsetHeight;
                                for (var i = 0; i < selList.length; i++) {
                                    var sl = selList[i].offsetWidth + selList[i].offsetLeft;
                                    var st = selList[i].offsetHeight + selList[i].offsetTop;
                                    if (sl > _l && st > _t && selList[i].offsetLeft < _l + _w && selList[i].offsetTop < _t + _h) {
                                        if (selList[i].className.indexOf("seled") == -1) {                                     
                                            selList[i].className = selList[i].className + " seled";
                                            vnode.context.$refs.table.toggleRowSelection(vnode.context.tableData[i],true)
                                            //把选中的都存入到table标签中的已选中
                                            if(vnode.context.tableData[i])
                                                vnode.context.multipleSelection.push(vnode.context.tableData[i]);
                                        }
                                    } else {
                                        if (selList[i].className.indexOf("seled") != -1 ) {                                  
                                            selList[i].className = "el-table__row";
                                            vnode.context.$refs.table.toggleRowSelection(vnode.context.tableData[i],false);
                                            vnode.context.multipleSelection.forEach((ele,i)=>{
                                                //这里没用对象是否相等用的是传入table中的唯一的myKey字段
                                                if(ele[vnode.context.myKey]==vnode.context.tableData[i][vnode.context.myKey] ){
                                                    vnode.context.multipleSelection.splice(i,1);
                                                }
                                            })
                                        }
                                    }
                                }
    
                            }
                            vnode.context.clearEventBubble(evt);
                        };
                        //方法是确定列表到屏幕的位置
                        function getX(obj){
                            var parObj=obj;
                            var left=obj.offsetLeft;
                            while(parObj=parObj.offsetParent){
                                left+=parObj.offsetLeft;
                            }
                            return left;
                        }
                        //方法是确定列表到屏幕的位置
                        function getY(obj){
                            var parObj=obj;
                            var top=obj.offsetTop;
                            while(parObj = parObj.offsetParent){
                                top+=parObj.offsetTop;
                            }
                            return top;
                        }
                        //在鼠标抬起后做的重置
                        document.onmouseup = function () {
                            //把鼠标移动事初始化
                            document.onmousemove=null;
                            if (selDiv) {
                                document.getElementsByClassName("el-table__body")[0].removeChild(selDiv);
                            }
                            selList = null, _x = null, _y = null, selDiv = null, startX = null, startY = null, evt = null;
                            vnode.context.mouseflag = false;
                            vnode.context.$handleSelect();
                        };
                    };
                }
            }
        },
        components: {
            airContexMenu,
        },
        props: {
            //对于列表中唯一的字段myKey默认为id
            myKey: {
                type: String,
                default: "id"
            },
            //列表的数据
            tableData: {
                type: Array,
                default: () => []
            },
            //传过来的表头信息
            columData: {
                type: Array,
                default: () => []
            },
            //有没有checkbox
            isType : {
                type: String,
                default: "selection"
            },
            //右键菜单
            menuList:{
                type: Array,
                default: () => []
            },
            //分页的总页数
            pageTotal:{
                type:Number,
                default: 0
            }
        },
        data() {
            return {
                //指令中确定的时候是鼠标按下事件
                mouseflag: false,
                //选中的数组
                multipleSelection: [],
                //控制右键菜单弹出显示
                dialogVisible:false,
                //右键鼠标的位置
                position:{
                    left:0,
                    top:0
                },
                //控制右键显示隐藏
                toggleShow :false,
                //分页当前的页数
                currentPage:1 ,
                //当前右键点击的列
                currentRow:[],
                //当前滚动的距离,
                targetScroll:0
            }
        },
        methods: {
            //清除默认事件
            clearEventBubble(evt) {
                if (evt.stopPropagation)
                    evt.stopPropagation();
                else
                    evt.cancelBubble = true;
                if (evt.preventDefault)
                    evt.preventDefault();
                else
                    evt.returnValue = false;
            },
            //列表单击选中事件
            rowClick(row, event, column) {
                let flag=true;            
                //确定当前的row的index
                var index = 0;
                this.tableData.forEach((ele,i)=>{
                    if(ele[this.myKey] == row[this.myKey]){
                        index = i+1;
                    }
                })
                this.toggleShow = false;
                //如果有就移除
                this.multipleSelection.forEach((ele,i)=>{
                    if(ele[this.myKey]==row[this.myKey]){
                        this.$refs.table.toggleRowSelection(row,false);
                        //后期优化吧 element的方法用不了 只能自己改变类名
                        this.$refs.table.$el.getElementsByTagName("tr")[index].className = "el-table__row";
                        this.multipleSelection.splice(i,1);
                        flag = false;
                    }
                })
                //如果没有就push
                if(flag){
                    this.$refs.table.toggleRowSelection(row,true);
                    this.multipleSelection.push(row);
                    //后期优化吧 element的方法用不了 只能自己改变类名
                    this.$refs.table.$el.getElementsByTagName("tr")[index].className = "el-table__row seled";
                }        
            },
            //列表右键点击事件
            rowContextmenu(row, event){
                //为当前的row赋值
                this.currentRow = row;
                //阻止默认右键点击事件
                event.returnValue = false;
                //获取右键坐标
                this.position.left = event.clientX
                this.position.top = event.clientY
                //菜单出现的flag
                this.toggleShow = true;
                //显示弹出窗    
            },
            //右键菜单弹出事件
            menuClick(item){
                //右键点击以后隐藏
                this.toggleShow=false;
                this.$emit("rowContextmenu",item,this.currentRow)
            },
            //每页条数变化 ui定死每页20条
            handleSizeChange(val) {
                // console.log(`每页 ${val} 条`);
            },
            //当前页变化
            handleCurrentChange(val) {
                this.currentPage = val;
                this.$emit('currentPageChange',this.currentPage)
            },
            //当批量选中结束调用
            $handleSelect(){
                this.$emit('handleSelect',this.multipleSelection)
            },
            //监听表格的滚动
            handleScroll(e){
                this.targetScroll = e.target.scrollTop;          
            },
            //
            headerClassName(){
                return "air-table-header__class";
            }
        },
        computed: {
           
        },
        created() {
            
            //确保右键菜单消失
            document.onclick = ()=>{
                this.toggleShow=false;
            }
        },
        mounted() {
            
        }
    }
    
    </script>
    
    <style lang="scss">
        @import "../../../public/style/mixin.scss";
    
        .air-table-wrapper {
            @include wh(100%, 100%);
            .seled {
                background: #f5f5f5 !important;
            }
            .no-seled{
                background: #ffffff !important;
            }
            .el-table__body tr{
                cursor: pointer;
                box-sizing: border-box;
                border-top:1px solid #f5f5f5;
                border-bottom:1px solid #f5f5f5;
            }
            .air-table-header__class th{
                border-bottom:1px solid #f5f5f5 !important;
            }
            .el-table__body td{
                border-bottom:1px solid #f5f5f5;
            }
            .hover-row {
                border-top:1px solid #f5f5f5;
                border-bottom:1px solid #f5f5f5;
                background: #fafafa;
            }
            .el-table__append-page{
                padding-top:48px;
                padding-bottom:48px;
                .el-pagination{
                    text-align: right;
                }
            }
            .el-table__append-info{
                position: absolute;
                bottom:0px;
                100%;
                .el-pagination{
                    text-align: right;
                }
            }
            .air-table__context--menu{
                box-shadow:0 3px 5px -1px rgba(0,0,0,.2), 0 6px 10px 0 rgba(0,0,0,.14), 0 1px 18px 0 rgba(0,0,0,.12);
                .air-table__context--list {
                    cursor: pointer;
                    height: 48px;
                    @include flexCenter(flex-start,center);
                    .air-table__context--icon{
                        font-size: 14px;
                        margin-left:20px;
                        color:#757575;
                    }
                    .air-table__context--info{
                        font-size: 14px;
                        margin-left:20px;
                        color:#212121;
                    }
                }
                .air-table__context--list:hover{
                    background: #f5f5f5;
                }
            }
            
            
        }
    </style>
    

      子组件中的右键菜单组件

    export default {
        name: 'airContexMenu',
        props: {
            position: {
                type: Object,
                default: () => {
                    return {
                        top: 0,
                        left: 0
                    }
                }
            },
            toggleShow:{
                type:Boolean,
                default: false
            },
            menuList : {
                type: Array,
                default: () => []
            }
        },
        render(h) {
            var self = this;
            var menuInfo = [];
            this.menuList.forEach((ele)=>{
                menuInfo.push(h('li',{
                    style: {
                        "100%",
                        display:"flex"
                    },
                    class: ['air-table__context--list','ripple'],
                    on: {   
                            click:function (){
                                self.$emit('menuClick', ele)
                            }
                        }
                    },
                [
                    h('i', {
                        class: [ele.icon,'air-table__context--icon']
                    }),
                    h('span',{class:['air-table__context--info']}, ele.name)
                ]))
            })
            return h(
                'div', {
                    style: {
                      "300px",
                      padding: "8px 0px",
                      position:"fixed",
                      left: this.position.left + "px",
                      top: this.position.top + "px",
                      display: this.toggleShow ? "block" : "none",
                      zIndex:99999,
                      backgroundColor:"#fff",
                      borderRadius:"4px"
                    },
                    class: ['air-table__context--menu']
                },
                menuInfo
            );
        },
        computed: {
            
        },
        data() {
            return {
            
            };
        },
        created() {
            
        },
        methods: {
            menuClick(){
                
            }
        }
    };
    

      

  • 相关阅读:
    继承与多态,Instanceof关键字
    面向对象,单例模式
    方法
    数组
    流程控制
    基础语法
    连接linux四大远程工具
    MYSQL-索引的设计
    银行一类(Ⅰ类)、二类(Ⅱ类)、三类(Ⅲ类)账户区别是什么?
    真正有效的学习
  • 原文地址:https://www.cnblogs.com/smallteeth/p/9382529.html
Copyright © 2011-2022 走看看