先來看實現效果。
1.遇到問題
因爲隨着功能的增多,table操作欄中的功能按鈕增多,操作列長度就增長,導致不是很美觀。所以產品要求超過三個按鈕就將多餘的按鈕隱藏在一個按鈕中。點擊這個按鈕實現展開和摺疊其餘按鈕的效果。
這個需求是UI組件庫中沒有實現的。所以要求自己實現。
2.解決思路
因爲以前操作欄按鈕的實現是直接在視圖template中寫死的。所以我想到是不是可以通過修改UI組件庫中table組件接收的數據進行處理與展示。經過研究後發現它是通過編譯生成VDOM處理的,所以很難直接處理VDOM,這種方式就不行了。
後來想到能不能將按鈕先定義成數據數組,通過處理後再渲染操作按鈕。通過嘗試後這種方式是可行的。一般按鈕有按鈕圖標、按鈕名稱、按鈕權限、和按鈕點擊這幾個功能。所以最後將每個按鈕定義爲下面的數據結構。
[{
icon: 'edit',//圖標icon 必填 String
name: '編輯',//圖標title 必填 String
handler: function (row, scope) {},//圖標點擊操作方法,返回兩個參數行數據和scope數據 必填 Function
v_if: function (row, scope) {}//圖標是否被操作欄包含條件方法,返回兩個參數行數據和scope數據,返回值爲true就被包含,false不會被包含 非必填 Function
v_noBtn: 'assetsManage_accountManage'//圖標是否被操作欄包含條件字符串
}]
其中v_if和v_noBtn是用來處理按鈕權限的。handler是點擊觸發函數。最後通過權限過濾後的按鈕個數來判斷按鈕的是否需要隱藏。大於三個和不大於三個的按鈕分別渲染爲對應的視圖。這時候又遇到了一個問題,由於table組件樣式的限制導致按鈕的展示與隱藏彈出框不能超過當前列長度。超出了就隱藏。這個問題本來是想設置定位來實現的,但是由於UI組件一些限制沒辦法實現。所以最後想法是能不能將這個彈出框DOM渲染在表格或者表格外層div中。這樣就解決了這個問題。發現UI庫裏面有個Popper組件,查看源碼後發現它是直接渲染在body中的,正合我意,修改下vue-popper.js,如果獲取到props就渲染在對應的元素節點中,如果沒有就渲染在body中。
if (this.appendToTable){
document.querySelector(this.appendToTable).appendChild(this.popperElm);
} else if (this.appendToBody){
document.body.appendChild(this.popperElm);
}
這樣這個需求就實現了。
3.用法
- 此組件接收三個props:btnData(操作按鈕數據對象數組)、scope(table上的scope對象)、option配置項
//默認props:
btnData:[],
option:{
isHidden:true,//是否開啓操作欄隱藏設置,默認開啓
showNum:3//如果isHidden爲true時,個數大於3就會隱藏,默認是3
appendId: '.s-table',//將浮動欄添加到對應id或者class節點中。或者.xxx。傳空字符串是添加到body中。
trigger: 'click',//觸發方式,傳值可查看Popper UI組件trigger屬性
placement: 'left'//方向,傳值可查看Popper UI組件placement屬性
}
- btnData數組中的對象接收5個屬性:
{
icon: 'edit',//圖標icon 必填 String
name: '編輯',//圖標title 必填 String
handler: function (row, scope) {},//圖標點擊操作方法,返回兩個參數行數據和scope數據 必填 Function
v_if: function (row, scope) {}//圖標是否被操作欄包含條件方法,返回兩個參數行數據和scope數據,返回值爲true就被包含,false不會被包含 非必填 Function
v_noBtn: 'assetsManage_accountManage'//圖標是否被操作欄包含條件字符串
},
其中v_if和v_noBtn只要有一個返回值爲false當前行操作欄中就不包含。
4.實例
此處代碼和element標籤上有些差異。是因爲對element進行了二次處理。除了標籤改變外,其餘大多是沒改變的。組件就不提供了,可以按照上面的思路和具體需求自己去寫一個。
<s-table>
<s-table-column label="操作" fixed="right">
<template slot-scope="scope">
<button-set :scope="scope" :btnData="btnData()" :option="tableOption"></button-set>
</template>
</s-table-column>
</s-table>
<script>
import buttonSet from '@/components/tableHandleHidden/buttonSet';
export default {
components: {
buttonSet
}
data() {
return {
tableOption: {
isHidden: true,
showNum: 3,
appendId: '#realpagetable_1',
trigger: 'click',
placement: 'left'
}
}
},
methods: {
btnData() {
let vm = this;
return [
{
icon: 'eye',
name: '查看資產詳情',
v_noBtn: 'assetsManage_viewAsset',
handler: function (row, scope) {
vm.gotoAssetDetail(row)
}
},
{
icon: 'edit',
name: '編輯',
handler: function (row, scope) {
vm.curUuid = scope.row.uuid;
vm.$router.push(`assets_list/assetEdit/${vm.curUuid}/0`);
},
v_if: function (row, scope) {
return vm.isConfigAdminCheck(scope.row.monitorItcomp) || vm.judgeRoleBtn('assetsManage_editAsset')
}
}
]
}
}
}
</script>