前言:主要是 table 表格框選功能
實現功能如下:
- 表格框選功能
- 右鍵操作功能(刪除、檢視、編輯)
- 分頁功能
- 表頭分類篩選功能
- 回顯功能(顯示預設選中資料)
- 排序功能
- 行禁用不可選功能
不說廢話,直接上程式碼,簡單粗暴。。。
1、元件
/*
* @auhor : 開發部-前端組-李鑫超
* @property { tableData : {Array} 表格資料 add v-1.0.0 }
* @property { columData : {Array} 表頭資料 add v-1.0.0 }
* @property { menuList : {Array} 右鍵選單 add v-1.0.0 }
* @property { myKey : {String} 唯一標識。 add v-1.0.0 }
* @property { isRadio : {Boolean} 是否單選,預設false。 add v-1.0.0 }
* @property { showpage : {Boolean} 是否顯示分頁,預設false。 add v-1.0.0 }
* @property { currentPage : {Number} 當前頁,預設1。 add v-1.0.0 }
* @property { pageSize : {Number} 每頁顯示條目個數, 預設20。 add v-1.0.0 }
* @property { pageTotal : {Number} 總條目數。 add v-1.0.0 }
* @property { backMultipleSelection : {Array} 回顯資料。 add v-1.0.0 }
* @property { emptyText : {String} 空資料時顯示的文字內容,預設暫無資料。 add v-1.0.0 }
* @property { rowDisabled : {String} 行禁用時,根據該欄位判斷。 add v-1.0.0 }
* @property { pageDataFlag : {Boolean} 翻頁時,是否儲存其他頁面選中的資料,預設值false。 add v-1.0.0 }
* @property { sortable : {Boolean,String} 對應列是否可以排序,如果設定為 'custom',則代表使用者希望遠端排序,需要監聽 Table 的 sort-change 事件。 add v-1.0.0 }
* @method { makesure : {Function(data)} 表頭tree點選事件 add v-1.0.0 }
* @method { menuClick : {Function(item)} item 表格右鍵選項事件 add v-1.0.0 }
* @method { currentPageChange : {Function(page)} 當前頁改變事件事件 add v-1.0.0 }
* @method { handleSelect : {Function(data)} 選中資料時會觸發該事件 add v-1.0.0 }
* @method { sortChange : {Function(column, prop, order)} 點選表頭排序按鈕會觸發該事件 add v-1.0.0 }
* @version 1.2.0
* @edit: 2018/10/24
*/
<template>
<div class='air-table-wrapper'>
<el-table ref="table"
:show-header="true"
:data="tableData"
tooltip-effect="dark"
style="width: 100%;"
:height="height"
:header-row-class-name="headerClassName"
id="table"
@row-click="rowClick"
@selection-change="selectionChange"
@select-all="selectAll"
@select="selectItem"
@row-contextmenu="rowContextmenu"
@row-dblclick="rowDblclick"
@header-click="headerClick"
@empty-text="emptyText"
@sort-change="sortChange"
v-drag>
<!-- checkbox -->
<el-table-column type="selection"
width="56"
align="center"
:selectable="selectable"></el-table-column>
<!-- index 序號 -->
<el-table-column v-if="isType == 'index'"
:index="indexMethod"
type="index"
:label="'序號'"
width="56"
align="center"></el-table-column>
<!--列表的表頭迴圈-->
<el-table-column v-for="(column, index) in columData"
:key="index"
:sortable="sortable"
: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
v-if="currentshowPage">
<div :class="showAdd ? 'el-table__append-pageAdd el-table__append-page': 'el-table__append-page'">
<el-pagination @size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="page"
:page-size="pageSize"
layout="total, prev, pager, next"
:total="pageTotal">
</el-pagination>
</div>
</template>
<!-- 新增按鈕 -->
<template slot=append
v-if="showAdd">
<airButton buttonType="colorButtonroundOrange"
@click="addClick"></airButton>
</template>
</el-table>
<!-- 右鍵選單 -->
<air-contex-menu v-if="menuList.length"
:position="position"
:toggleShow="toggleShow"
:menuList="menuList"
@menuClick="menuClick">
</air-contex-menu>
<!-- 彈出窗 -->
<tree-dialog ref="treeDialog"
:pid="treePid"
:name="treeName"
:id="treeId"
:data="treeData"
@makesure=makesure
placeholder="輸入資訊,按回車搜尋"
:title='treeTitle'>
</tree-dialog>
</div>
</template>
<script>
import airContexMenu from "./contextMenu.js";
import treeDialog from "@/components/newCommon/dialog/treeDialog.vue";
export default {
name: "airtable",
// 框選的指令
directives: {
drag: {
// 指令的定義
inserted: function (el, binding, vnode) {
var oDiv = el;
vnode.context.tableTop = getY(oDiv);
vnode.context.tableLeft = getX(oDiv);
//方法是確定列表到螢幕的位置
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;
}
// 禁止右鍵預設選單
oDiv.oncontextmenu = function () {
return false;
}
oDiv.onmousedown = function (ev) {
// 防止奇葩操作
if ([2, 3, 4, 5].indexOf(ev.buttons) > -1) {
if (selDiv) {
oDiv.getElementsByClassName("el-table__body")[0].removeChild(selDiv);
}
return
}
// 獲取當前scrollTop
var scrollingTop = vnode.context.targetScroll;
if (vnode.context.isRadio) return;
vnode.context.$selectState(true);
//初始化不顯示
vnode.context.toggleShow = false;
//確保使用者在移動滑鼠的時候只初始化一次選中
var flag = true;
// 獲取表格的寬高
let tableWidth = vnode.context.$el.clientWidth;
let tableHeight = vnode.context.$el.clientHeight;
//用來儲存列表
var selList = [];
//獲得指令下的dom對應的表格
var fileNodes = oDiv.getElementsByTagName("tr");
//獲得滑鼠
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 solid rgba(255,165,22,0.38);background-color:rgba(0,0,0,0.38);z-index:1000;filter:alpha(opacity:60);opacity:0.6;display:none;";
selDiv.id = "selectDiv";
oDiv.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;
}
vnode.context.selectItemFlag = false;
// 為了確保只有一次的渲染每次框選都把預設選中為空(針對當前頁)
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]);
}
}
// 判斷翻頁是否儲存選中資料
// if (vnode.context.pageDataFlag) {
// 判斷當前頁是否有選中的
vnode.context.tableData.forEach((item) => {
vnode.context.$refs.table.toggleRowSelection(item, false);
vnode.context.multipleSelection.forEach((ele, i) => {
if (item[vnode.context.myKey] == ele[vnode.context.myKey]) {
vnode.context.multipleSelection.splice(i, 1);
i = i - 1;
}
})
})
// } else {
// vnode.context.multipleSelection = []
// }
flag = false;
}
// 判斷滑鼠移動是否超出在當前表格區域
if (_x <= left || _x >= left + tableWidth || _y <= top || _y >= top + tableHeight) {
document.onmousemove = null;
if (selDiv) {
oDiv.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();
}
if (vnode.context.mouseflag) {
if (selDiv.style.display == "none") {
selDiv.style.display = "";
}
var scrolling = oDiv.getElementsByClassName("el-table__body-wrapper");
// 兩個表格的時候需增加滾屏的高度
// var main_scrolling=document.getElementsByClassName("common_table_height");
// selDiv.style.left = Math.min(_x, startX)-left+scrolling[0].scrollLeft +main_scrolling[0].scrollLeft+ "px";
// console.log(scrolling)
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+main_scrolling[0].scrollTop+ "px";
selDiv.style.top =
Math.min(_y, startY) - top - oDiv.getElementsByClassName("is-leaf")[0].offsetHeight + scrollingTop + "px";
selDiv.style.width = Math.abs(_x - startX) + "px";
if (scrolling[0].scrollTop > scrollingTop) {
selDiv.style.height = Math.abs(_y - startY) + scrolling[0].scrollTop + "px";
} else {
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 && !vnode.context.tableData[i][vnode.context.rowDisabled]) {
selList[i].className = selList[i].className + " seled";
vnode.context.$refs.table.toggleRowSelection(
vnode.context.tableData[i],
true
)
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
)
let index = vnode.context.multipleSelection.indexOf(vnode.context.tableData[i])
vnode.context.multipleSelection.splice(index, 1)
}
}
}
// ---------------- 關鍵演算法結束---------------------
}
if (document.onmousemove) {
vnode.context.clearEventBubble(evt);
}
};
//在滑鼠抬起後做的重置
oDiv.onmouseup = function () {
//把滑鼠移動事初始化
document.onmousemove = null;
if (selDiv) {
oDiv.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.$selectState(false);
// 防止重複$handleSelect()事件
if (!vnode.context.selectItemFlag) {
vnode.context.$handleSelect();
vnode.context.selectItemFlag = false;
}
};
};
}
}
},
components: {
airContexMenu, treeDialog
},
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
},
// 每頁顯示條數
pageSize: {
type: Number,
default: 20
},
// 當前頁
currentPage: {
type: Number,
default: 1
},
// 當表格需要單選的時候
isRadio: {
type: Boolean,
default: false
},
// table 回顯資料
backMultipleSelection: {
type: Array,
default: () => []
},
// 是否顯示分頁
showPage: {
type: Boolean,
default: true
},
// 是否顯示新增按鈕
showAdd: {
type: Boolean,
default: false
},
// 表格高度
height: {
type: [Number, String],
default: 500
},
// 空資料時顯示的文字內容
emptyText: {
type: String,
default: "暫無資料"
},
// 行禁用事件
rowDisabled: {
type: String,
default: "disabled"
},
// 翻頁是否儲存資料
pageDataFlag: {
type: Boolean,
default: true
},
// 對應列是否可以排序,如果設定為 'custom',則代表使用者希望遠端排序,需要監聽 Table 的 sort-change 事件
sortable: {
type: [Boolean, String],
default: false
}
},
data() {
return {
//指令中確定的時候是滑鼠按下事件
mouseflag: false,
//選中的陣列
multipleSelection: [],
//控制右鍵選單彈出顯示
dialogVisible: false,
//右鍵滑鼠的位置
position: {
left: 0,
top: 0
},
//控制右鍵顯示隱藏
toggleShow: false,
//分頁當前的頁數
page: this.currentPage,
//當前右鍵點選的列
currentRow: [],
//當前滾動的距離,
targetScroll: 0,
// 是否點選單選按鈕
selectItemFlag: false,
// 表頭tree 資料
treeData: [],
treeName: '',
treePid: '',
treeId: '',
treeTitle: "",
// 表格top距離
tableTop: null,
tableLeft: null,
timer: null,
currentshowPage: true
};
},
methods: {
// 換算index
indexMethod(index) {
return index + (this.page - 1) * this.pageSize + 1;
},
//清除預設事件
clearEventBubble(evt) {
if (evt.stopPropagation) evt.stopPropagation();
else evt.cancelBubble = true;
if (evt.preventDefault) evt.preventDefault();
else evt.returnValue = false;
},
//列表單擊選中事件
rowClick(row, event, column) {
if (row.disabled) {
return
}
// 確定當前的row的index
var index = 0;
this.tableData.forEach((ele, i) => {
if (ele[this.myKey] == row[this.myKey]) {
index = i + 1;
}
});
let flag = false;
this.toggleShow = false;
// 單選
if (this.isRadio) {
// 每次點選重置
var dom = this.$refs.table.$el.getElementsByTagName("tr");
this.tableData.forEach(ele => {
this.$refs.table.toggleRowSelection(ele, false);
});
for (var i = 1; i < dom.length; i++) {
dom[i].className = "el-table__row";
}
this.$refs.table.toggleRowSelection(row, true);
this.$refs.table.$el.getElementsByTagName("tr")[index].className =
"el-table__row seled";
this.multipleSelection = Array.of(row)
this.$handleSelect();
return
}
this.selectItemFlag = true;
// 如果有就刪除
this.multipleSelection.forEach((ele, i) => {
if (ele[this.myKey] == row[this.myKey]) {
this.$refs.table.toggleRowSelection(row, false);
this.$refs.table.$el.getElementsByTagName("tr")[index].className =
"el-table__row";
flag = true;
this.multipleSelection.splice(i, 1)
}
});
// 如果沒有就push
if (!flag) {
this.$refs.table.toggleRowSelection(row, true);
//後期優化吧 element的方法用不了 只能自己改變類名
this.$refs.table.$el.getElementsByTagName("tr")[index].className =
"el-table__row seled";
this.multipleSelection.push(row)
}
this.$handleSelect();
},
//列表右鍵點選事件
rowContextmenu(row, event) {
if (row[this.rowDisabled]) {
return
}
//確定當前的row的index
var index = 0;
this.tableData.forEach((ele, i) => {
if (ele[this.myKey] == row[this.myKey]) {
index = i + 1;
}
});
// 每次點選重置
var dom = this.$refs.table.$el.getElementsByTagName("tr");
this.tableData.forEach(ele => {
this.$refs.table.toggleRowSelection(ele, false);
});
for (var i = 1; i < dom.length; i++) {
dom[i].className = "el-table__row";
}
this.$refs.table.toggleRowSelection(row, true);
this.$refs.table.$el.getElementsByTagName("tr")[index].className =
"el-table__row seled";
this.multipleSelection = Array.of(row)
this.$handleSelect();
//為當前的row賦值
this.currentRow = row;
//阻止預設右鍵點選事件
event.returnValue = false;
//獲取右鍵座標
this.position.left = event.clientX;
this.position.top = event.clientY;
//選單出現的flag
this.toggleShow = true;
//顯示彈出窗
this.$emit("contextmenu", row, event);
},
//右鍵選單彈出事件
menuClick(item) {
//右鍵點選以後隱藏
this.toggleShow = false;
this.$emit("rowContextmenu", item, this.currentRow);
},
//每頁條數變化 ui定死每頁20條
handleSizeChange(val) {
// console.log(`每頁 ${val} 條`);
},
// 當前頁變化
handleCurrentChange(val) {
this.page = val;
this.$emit("currentPageChange", this.page);
},
//當批量選中結束呼叫
$handleSelect() {
this.removal();
// 過濾掉禁用的資料
this.multipleSelection = this.multipleSelection.filter((item) => {
return !item[this.rowDisabled]
});
this.$emit("handleSelect", this.multipleSelection);
},
// 根據myKey去重
removal() {
let hash = {};
this.multipleSelection = this.multipleSelection.reduce((preVal, curVal) => {
hash[curVal[this.myKey]] ? '' : hash[curVal[this.myKey]] = true && preVal.push(curVal);
return preVal
}, [])
},
// 是否框選 state
$selectState(state) {
this.$emit("selectState", state);
},
// 選項發生改變事件 ZZ
selectionChange(val) {
// this.multipleSelection = val;
},
//監聽表格的滾動
handleScroll(e) {
this.targetScroll = e.target.scrollTop;
},
//當單選時觸發的事件
selectItem(selection, row) {
this.selectItemFlag = true;
this.rowClick(row);
},
//當表頭多選是觸發的事件
selectAll(selection) {
this.selectItemFlag = true;
var dom = this.$refs.table.$el.getElementsByTagName("tr");
if (this.isRadio) {
this.tableData.forEach(ele => {
this.$refs.table.toggleRowSelection(ele, false);
});
for (var i = 1; i < dom.length; i++) {
dom[i].className = "el-table__row";
}
this.multipleSelection = [];
this.$handleSelect();
return;
}
if (selection.length) {
for (var i = 1; i < dom.length; i++) {
//為了去掉表頭的tr從1開始
dom[i].className = "el-table__row seled";
}
// if(this.pageDataFlag){
this.multipleSelection = [...this.multipleSelection, ...selection];
// }else{
// this.multipleSelection = selection;
// }
this.removal();
} else {
for (var i = 1; i < dom.length; i++) {
dom[i].className = "el-table__row";
}
this.tableData.forEach((item) => {
this.multipleSelection.forEach((ele, i) => {
if (item[this.myKey] == ele[this.myKey]) {
this.multipleSelection.splice(i, 1)
i = i - 1;
}
})
})
}
this.$handleSelect();
},
//雙擊事件
rowDblclick(row, event) {
if (row.disabled) {
return
}
this.$emit("rowDblclick", row, event);
},
// 表頭點選事件
headerClick(column, event) {
if (event.target.nodeName === 'DIV')
this.columData.map((item, index) => {
if (item.name == column.label) {
if (item.tree && item.tree.data.length) {
this.$refs.treeDialog.$el.getElementsByClassName("el-dialog")[0].style.top = this.tableTop + 53 + 'px';
this.$refs.treeDialog.$el.getElementsByClassName("el-dialog")[0].style.left = this.tableLeft + (event.path[1].scrollWidth) * (index) + 55 + 'px';
this.treeData = item.tree.data;
this.treePid = item.tree.pid;
this.treeId = item.tree.id;
this.treeName = item.tree.name;
this.treeTitle = item.name;
this.$refs.treeDialog.dialogOpen();
}
}
})
},
// tree確定事件/
makesure(data) {
this.$emit('makesure', data);
},
// 新增按鈕點選事件
addClick() {
this.$emit('addClick');
},
// 初始化回顯資料
initMultipleSelection() {
this.$nextTick(() => {
var dom = this.$refs.table.$el.getElementsByTagName("tr");
this.$refs.table.clearSelection();
this.tableData.forEach((ele, i) => {
dom[i + 1].className = "el-table__row";
});
//為了傳過來的值進行回顯
if (this.backMultipleSelection.length > 0) {
this.backMultipleSelection.forEach(item => {
this.tableData.forEach((ele, i) => {
if (item[this.myKey] == ele[this.myKey] && !ele[this.rowDisabled]) {
this.$refs.table.toggleRowSelection(ele, true);
dom[i + 1].className = "el-table__row seled";
}
});
});
}
});
},
// 自適應分頁的位置
initPage() {
if (!this.currentshowPage) return
// 分頁顯示的位置
let obj = this.$refs.table.$el.getElementsByClassName("el-table__body-wrapper")[0];
// 判斷是否有滾動條
if (obj.scrollHeight > obj.clientHeight) {
this.$refs.table.$el.getElementsByClassName("el-table__append-wrapper")[0].style.cssText = "";
} else {
this.$refs.table.$el.getElementsByClassName("el-table__append-wrapper")[0].style.cssText = "position:absolute;right:0;bottom:0;";
}
},
// 行禁用事件
selectable(row, index) {
if (row[this.rowDisabled]) {
return false
} else {
return true
}
},
// 清空回顯資料
clearMultipleSelection() {
this.multipleSelection = [];
},
/*
*@method 表頭排序點選事件
*@param 1 column行資料
*@param 2 prop == "ascending" 排序
* prop == "descending" 降序
*@param 3 order排序規則
*@return {返回值型別} 返回值說明
*/
sortChange(column, prop, order) {
this.$emit("sortChange", column, prop, order);
}
},
watch: {
backMultipleSelection: {
handler: function (newVal, oldVal) {
//為了回顯
this.multipleSelection = newVal;
this.initMultipleSelection();
},
deep: true
},
currentPage: {
handler(newValue, oldValue) {
this.page = newValue;
},
immediate: true
},
showPage: {
handler(newValue, oldValue) {
this.currentshowPage = newValue;
},
immediate: true
},
tableData(val) {
/* 監聽table資料變化時(分頁操作),已選中資料做回顯 */
this.$nextTick(() => {
// 判斷翻頁是否儲存選中資料
// if (this.pageDataFlag) {
var dom = this.$refs.table.$el.getElementsByTagName("tr");
this.$refs.table.clearSelection();
this.tableData.forEach((ele, i) => {
dom[i + 1].className = "el-table__row";
});
//為了已選中資料進行回顯
if (this.multipleSelection.length > 0) {
this.multipleSelection.forEach(item => {
this.tableData.forEach((ele, i) => {
if (item[this.myKey] == ele[this.myKey] && !ele[this.rowDisabled]) {
this.$refs.table.toggleRowSelection(ele, true);
dom[i + 1].className = "el-table__row seled";
}
});
});
}
// }else{
// this.multipleSelection = [];
// }
this.initPage();
})
}
},
computed: {
// 通過滾動距計算陰影 class
headerClassName() {
if (this.targetScroll == 0) {
return "air-table-header__class"
} else if (this.targetScroll > 0 && this.targetScroll <= 100) {
return "air-table-header__class air-table-header__scroll1"
} else if (this.targetScroll > 100 && this.targetScroll <= 200) {
return "air-table-header__class air-table-header__scroll2"
} else {
return "air-table-header__class air-table-header__scroll3"
}
}
},
mounted() {
document.onclick = () => {
this.toggleShow = false;
};
this.multipleSelection = this.backMultipleSelection;
this.initMultipleSelection();
this.$refs.table.$refs.bodyWrapper.addEventListener('scroll', this.handleScroll);
this.timer = setTimeout(() => {
this.initPage();
}, 20);
},
beforeDestroy() {
this.$refs.table.$refs.bodyWrapper.removeEventListener('scroll', this.handleScroll);
clearTimeout(this.timer);
}
};
</script>
<style lang="scss">
@import "../../../public/style/mixin.scss";
.air-table-wrapper {
@include wh(100%, 100%);
%scroll-calss {
width: 100%;
height: 1px;
position: absolute;
top: 51px;
left: 0;
content: "";
z-index: 2;
}
.seled {
background: #f5f5f5 !important;
}
.no-seled {
background: #ffffff !important;
}
.el-table__body-wrapper {
overflow: auto;
}
.el-table__body tr {
cursor: pointer;
box-sizing: border-box;
border-top: 1px solid #f5f5f5 !important;
border-bottom: 1px solid #f5f5f5 !important;
}
.air-table-header__class th {
padding: 9px 0 !important;
box-sizing: border-box;
border-bottom: 1px solid #f5f5f5 !important;
}
.air-table-header__scroll1 {
position: relative;
&::after {
@extend %scroll-calss;
box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2),
0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12);
}
}
.air-table-header__scroll2 {
position: relative;
&::after {
@extend %scroll-calss;
box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2),
0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
}
}
.air-table-header__scroll3 {
position: relative;
&::after {
@extend %scroll-calss;
box-shadow: 0 3px 3px -2px rgba(0, 0, 0, 0.2),
0 3px 4px 0 rgba(0, 0, 0, 0.14), 0 1px 8px 0 rgba(0, 0, 0, 0.12);
}
}
.el-table__body td {
box-sizing: border-box;
border-bottom: 1px solid #f5f5f5;
}
.hover-row {
border-top: 1px solid #f5f5f5;
border-bottom: 1px solid #f5f5f5;
background: #fafafa;
}
.el-table__append-page {
.el-pagination {
text-align: right;
margin: 48px 0;
.btn-prev {
@extend %airLeft;
}
.btn-next {
margin-right: 0px;
@extend %airRight;
}
.el-pager li {
@extend %elPagerLi;
}
.el-pagination__total {
@extend %elPaginationTotal;
}
}
.el-pagination button:disabled {
color: #bdbdbd;
}
}
.el-table__append-pageAdd {
.el-pagination {
margin: 48px 0 76px !important;
.btn-prev {
@extend %airLeft;
}
.btn-next {
margin-right: 0px;
@extend %airRight;
}
.el-pager li {
@extend %elPagerLi;
}
.el-pagination__total {
@extend %elPaginationTotal;
}
}
.el-pagination button:disabled {
color: #bdbdbd;
}
}
.air-table__context--menu {
box-shadow: 0 3px 5px -1px rgba(0, 0, 0, 0.2),
0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12);
.air-table__context--list {
cursor: pointer;
height: 48px;
@include flexCenter(flex-start, center);
.air-table__context--icon {
font-size: 20px;
margin-left: 20px;
color: #757575;
}
.air-table__context--info {
font-size: 14px;
margin-left: 20px;
color: #212121;
}
}
.air-table__context--list:hover {
background: #f5f5f5;
}
}
.el-table th {
padding: 9px 0 !important;
}
.air-treeDialog-wrappers .el-dialog {
margin: 0 !important;
}
.el-table-column--selection .cell {
padding-left: 20px;
padding-right: 10px;
}
}
</style>
複製程式碼
2、css樣式
.air-table-wrapper {
display: flex;
flex-direction: column;
@include wh(100%, 100%);
.el-table__body {
overflow: hidden;
// padding-bottom: 139px;
}
.el-table__body td .concat-table-container {
max-width: 350px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
cursor: pointer
}
.el-table__fixed-body-wrapper {
position: relative
}
.el-table__body tr {
height: $tableRowHeight;
}
.el-table__body-wrapper .is-scrolling-none {
height: auto !important;
}
.el-table {
width: 100%;
// min-height: 900px;
// height:-webkit-calc(100% - 56px) !important;
td {
border-bottom: none;
height: $tableRowHeight;
padding: 0px;
max-width: 400px;
}
th.is-leaf {
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
height: 53px;
font-size: 16px;
color: rgba(0, 0, 0, 0.87);
}
th {
&:first-child {
// border-left: 4px solid #fff;
//text-align: center
}
.cell {
height: 34px !important;
font-weight: 100;
line-height: 34px;
overflow: visible !important;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 400px;
}
}
.el-table__body {
tr {
td:first-child {
// border-left: 4px solid #fff;
//text-align: center
}
}
tr.hover-row {
td {
background: rgba(0, 0, 0, 0.02)
}
// td:first-child{border-left: 4px solid $themeColor}
}
tr.current-row {
td {
background: rgba(0, 0, 0, 0.04)
}
// td:first-child{border-left: 4px solid $themeColor}
}
.el-checkbox__inner{
@include wh(16px, 16px);
border: 2px solid #bdbdbd;
}
.el-radio__inner {
@include wh(16px, 16px);
border: 2px solid #bdbdbd;
border-radius: 0px
}
}
.el-table__header {
.el-checkbox__inner {
@include wh(16px, 16px);
border: 2px solid #bdbdbd;
}
.el-checkbox__input.is-indeterminate .el-checkbox__inner::before{
top: 7px;
}
}
.el-checkbox__inner::after {
-webkit-box-sizing: content-box;
box-sizing: content-box;
content: "";
border: 2px solid #fff;
border-left: 0;
border-top: 0;
height: 7px;
left: 4px;
position: absolute;
top: 1px;
}
.el-radio__label {
display: none
}
.el-radio__inner::after {
-webkit-box-sizing: content-box;
box-sizing: content-box;
content: "";
border: 2px solid #fff;
transform: rotate(45deg) scaleY(1);
border-left: 0;
border-top: 0;
height: 7px;
left: 4px;
position: absolute;
top: 1px;
border-radius: 0px;
background: none
}
.el-radio__input.is-checked .el-radio__inner::after {
transform: rotate(45deg) scaleY(1);
}
}
}
複製程式碼
3、contextMenu.js
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(){
}
}
};
複製程式碼
3、treeDialog.vue
/*
* @property { data : {Array} 介面傳來的陣列 }
* @property { showCheckbox : {Boolean} 是否顯示多選小方框 }
* @property { placeholder : {String} 提示語,上方搜尋框提示語。 }
* @method @check : 父元件使用check來接收已選中的所有資料組成的陣列
* @property { width : {String} 彈窗的寬度可以傳50%也可以傳200px }
* @property { title : {String} 彈窗上方的名字 }
* @property { showScreen : {Boolean} 是否需要篩選框 }
* @property { id : {String} id欄位 }
* @property { pid : {String} 父id欄位 }
* @property { name : {String} name欄位 }
* @method @nodeclick : 節點被點選時的回撥
* @property { defaultExpandAll : {Boolean} 是否預設展開 }
* @method @dialogOpen 開啟彈出框
* @method @dialogClose 關閉彈出框
* @method closeOnClickModal 是否可以點選遮罩層來關閉
* @method close 關閉事件
* @version 1.0.0
* @edit: 2018/8/2
*/
<template>
<div class="air-treeDialog-wrappers">
<el-dialog :title="treeTitle"
:visible.sync="dialogVisible"
:width="width"
@close="closed"
:before-close = "beforeclose">
<commonfiltertree :placeholder="placeholder"
:data="allData"
:showCheckbox="showCheckbox"
@check='getcheckdata'
:showScreen="showScreen"
@click='getCurrentKey'
@checkkey='getCheckedKeys'
:defaultExpandAll="defaultExpandAll"
:defaultCheckedKeys="defaultCheckedKeys"
:id="treeId"
:pid="treePid"
:name="treeName"
:isfilterText="isfilterText"
:close-on-click-modal="closeOnClickModal"
ref="tree"></commonfiltertree>
<div class="foot">
<airButton class="foot-button"
@click="dialogClose"
buttonType="colorButtonOrange"
buttonName="確定"></airButton>
</div>
</el-dialog>
</div>
</template>
<script>
import commonfiltertree from "@/components/newCommon/tree/tree.vue";
export default {
props: {
//提示語,上方搜尋框提示語
placeholder: {
type: String,
default: ""
},
//處理好的資料
data: {
type: Array,
default: () => []
},
// 是否顯示多選小方框
showCheckbox: {
type: Boolean,
default: true
},
//彈窗寬度
width: {
type: String,
default: "360px"
},
//題目(水費電費水電費)
title: {
type: String,
default: ""
},
//是否需要篩選框
showScreen: {
type: Boolean,
default: true
},
//是否預設展開
defaultExpandAll: {
type: Boolean,
default: false
},
//id 的欄位名
id: {
type: String,
default: "id"
},
//父id 的欄位名
pid: {
type: String,
default: "pid"
},
//內容的欄位名
name: {
type: String,
default: "name"
},
// //回顯陣列
// defaultCheckedKeys: {
// type: Array,
// default: () => []
// }
closeOnClickModal: {
type: Boolean,
default: true
}
},
components: {
commonfiltertree
},
data() {
return {
filterText: '',
countent: "",
checkbox: this.showCheckbox,
data1: new Array,
dialogTableVisible: false,
screen: this.showScreen,
dialogVisible: false,
allData: this.data,
treeName: this.name,
treeId: this.id,
treePid: this.pid,
treeTitle: this.title,
checkKeyData: [],
isfilterText: false,
defaultCheckedKeys: []
};
},
watch: {
filterText(val) {
this.$refs.tree2.filter(val);
},
data(val) {
this.allData = val;
},
pid(val) {
this.treePid = val;
},
id(val) {
this.treeId = val;
},
name(val) {
this.treeName = val;
},
title(val) {
this.treeTitle = val;
}
},
methods: {
getcheckdata(data) {
//有多選框的時候返回的data陣列
this.$emit('check', data);
},
getCurrentKey(data) {
//點選的時候返回當前點選的key
this.checkKeyData = data;
this.defaultCheckedKeys[0] = data.id;
console.log(this.defaultCheckedKeys)
this.$emit('click', data);
},
getCheckedKeys(data) {
//有多選框時返回的key所組成的陣列
this.checkKeyData = data;
this.$emit('checkkey', data);
},
//開啟彈出框
dialogOpen() {
this.dialogVisible = true;
this.isfilterText = false;
},
//關閉彈出框
dialogClose() {
this.dialogVisible = false;
this.isfilterText = true;
this.$emit('makesure', this.checkKeyData);
},
//關閉返回
closed() {
this.$emit("closed");
this.dialogVisible = false;
},
beforeclose(done){
this.dialogVisible = false;
this.$refs.tree.clearnodekey()
}
}
};
</script>
<style lang="scss" >
// @import "../../../public/style/common.scss";
.air-treeDialog-wrappers {
.el-dialog {
//min-height: 280px;
max-height: 568px;
border-radius: 4px;
box-shadow: 0px 20px 20px #777;
}
.el-dialog .el-dialog__header {
background-color: transparent;
}
.el-dialog .el-dialog__headerbtn .el-dialog__close {
color: #000;
}
.el-dialog__headerbtn {
top: 16px;
}
.el-dialog .el-dialog__header {
border-bottom: 1px solid #fafafa;
}
.el-dialog__body {
padding: 0;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
.expanded {
color: #616161;
}
.is-leaf {
color: transparent;
}
.air-tree-wrappers .el-tree {
margin-bottom: 0px;
}
.foot {
width: 100%;
height: 56px;
background-color: #fff;
border-top: 1px solid #f5f5f5;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
.foot-button {
float: right;
margin-top: 11px;
margin-right: 24px;
}
}
}
</style>
複製程式碼
結語: 通過操作 DOM 來改變 class ,感覺有點累贅,希望能有大神指出不足之處!