element table 实现鼠标拖拽选中
Posted smallteeth
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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,//固定列参数 width:"auto" }, { name: ‘名字‘, key: ‘name‘, isFixed: true,//固定列参数 width:"auto" }, { name: ‘地址‘, key: ‘address‘, isFixed: true,//固定列参数 width:"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-width: 200px; max-width: 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="width: 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;width: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; width: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: { width:"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: { width:"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(){ } } };
以上是关于element table 实现鼠标拖拽选中的主要内容,如果未能解决你的问题,请参考以下文章
element ui table排序sortable三种状态,怎么去掉默认状态