父组件
<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(){
}
}
};