element中table操作按鈕展示與折疊的實現(xiàn)示例
先來看實現(xiàn)效果。

1.遇到問題
因為隨著功能的增多,table操作欄中的功能按鈕增多,操作列長度就增長,導致不是很美觀。所以產(chǎn)品要求超過三個按鈕就將多余的按鈕隱藏在一個按鈕中。點擊這個按鈕實現(xiàn)展開和折疊其余按鈕的效果。
這個需求是UI組件庫中沒有實現(xiàn)的。所以要求自己實現(xiàn)。
2.解決思路
因為以前操作欄按鈕的實現(xiàn)是直接在視圖template中寫死的。所以我想到是不是可以通過修改UI組件庫中table組件接收的數(shù)據(jù)進行處理與展示。經(jīng)過研究后發(fā)現(xiàn)它是通過編譯生成VDOM處理的,所以很難直接處理VDOM,這種方式就不行了。
后來想到能不能將按鈕先定義成數(shù)據(jù)數(shù)組,通過處理后再渲染操作按鈕。通過嘗試后這種方式是可行的。一般按鈕有按鈕圖標、按鈕名稱、按鈕權(quán)限、和按鈕點擊這幾個功能。所以最后將每個按鈕定義為下面的數(shù)據(jù)結(jié)構(gòu)。
[{
icon: 'edit',//圖標icon 必填 String
name: '編輯',//圖標title 必填 String
handler: function (row, scope) {},//圖標點擊操作方法,返回兩個參數(shù)行數(shù)據(jù)和scope數(shù)據(jù) 必填 Function
v_if: function (row, scope) {}//圖標是否被操作欄包含條件方法,返回兩個參數(shù)行數(shù)據(jù)和scope數(shù)據(jù),返回值為true就被包含,false不會被包含 非必填 Function
v_noBtn: 'assetsManage_accountManage'//圖標是否被操作欄包含條件字符串
}]
其中v_if和v_noBtn是用來處理按鈕權(quán)限的。handler是點擊觸發(fā)函數(shù)。最后通過權(quán)限過濾后的按鈕個數(shù)來判斷按鈕的是否需要隱藏。大于三個和不大于三個的按鈕分別渲染為對應的視圖。這時候又遇到了一個問題,由于table組件樣式的限制導致按鈕的展示與隱藏彈出框不能超過當前列長度。超出了就隱藏。這個問題本來是想設(shè)置定位來實現(xiàn)的,但是由于UI組件一些限制沒辦法實現(xiàn)。所以最后想法是能不能將這個彈出框DOM渲染在表格或者表格外層div中。這樣就解決了這個問題。發(fā)現(xiàn)UI庫里面有個Popper組件,查看源碼后發(fā)現(xiàn)它是直接渲染在body中的,正合我意,修改下vue-popper.js,如果獲取到props就渲染在對應的元素節(jié)點中,如果沒有就渲染在body中。
if (this.appendToTable){
document.querySelector(this.appendToTable).appendChild(this.popperElm);
} else if (this.appendToBody){
document.body.appendChild(this.popperElm);
}
這樣這個需求就實現(xiàn)了。
3.用法
此組件接收三個props:btnData(操作按鈕數(shù)據(jù)對象數(shù)組)、scope(table上的scope對象)、option配置項
//默認props:
btnData:[],
option:{
isHidden:true,//是否開啟操作欄隱藏設(shè)置,默認開啟
showNum:3//如果isHidden為true時,個數(shù)大于3就會隱藏,默認是3
appendId: '.s-table',//將浮動欄添加到對應id或者class節(jié)點中?;蛘?xxx。傳空字符串是添加到body中。
trigger: 'click',//觸發(fā)方式,傳值可查看Popper UI組件trigger屬性
placement: 'left'//方向,傳值可查看Popper UI組件placement屬性
}
btnData數(shù)組中的對象接收5個屬性:
{
icon: 'edit',//圖標icon 必填 String
name: '編輯',//圖標title 必填 String
handler: function (row, scope) {},//圖標點擊操作方法,返回兩個參數(shù)行數(shù)據(jù)和scope數(shù)據(jù) 必填 Function
v_if: function (row, scope) {}//圖標是否被操作欄包含條件方法,返回兩個參數(shù)行數(shù)據(jù)和scope數(shù)據(jù),返回值為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: '查看資產(chǎn)詳情',
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>
@/components/tableHandleHidden/buttonSet組件:
<template>
<div class="buttonSet_all">
<div v-if="data.length===1">
<i v-for="(item, index) in data[0]" :key="index" :class="`iconfont icon-${item.icon}`" @click="item.handler(scope.row,scope,$event)" :title="item.name"></i>
</div>
<div v-else-if="data.length>1">
<i v-for="(obj, index) in data[0]" :key="index" :class="`iconfont icon-${obj.icon}`" @click="obj.handler(scope.row,scope,$event)" :title="obj.name"></i>
<s-popover
popper-class="buttonSet_style"
:append-to-table="option.appendId?option.appendId:''"
:ref="'popover'+scope.row.uuid"
:placement="option.placement?option.placement:'left'"
:trigger="option.trigger?option.trigger:'click'"
>
<ul class="s-dropdown-menu button-set-box" style="width:120px;">
<li style="overflow:hidden;text-overflow: ellipsis; white-space: nowrap; padding-left: 10px; padding-right: 10px;" class="s-dropdown-item" v-for="(obj, index) in data[1]" :key="index" @click="obj.handler(scope.row,scope,$event)">
<i :class="`iconfont icon-${obj.icon}`" :title="obj.name" style="font-size:14px; margin-right: 3px; color: #199FED"></i>
<span :title="obj.name">{{obj.name}}</span>
</li>
</ul>
<i class="iconfont icon-more" slot="reference"></i>
</s-popover>
</div>
</div>
</template>
<script>
// import {chunk} from 'lodash';
export default {
props: {
btnData: {
type: Array,
default: function() {
return []
}
},
scope: {
type: Object
},
option: {
type: Object,
default: function() {
return {
isHidden: true,
showNum: 3,
appendId: '.s-table',
trigger: 'click',
placement: 'left'
}
}
}
},
data() {
return {
data: []
}
},
computed: {},
created() {
this.init();
},
watch: {
scope(val) {
this.init();
}
},
methods: {
init() {
let arr = [];
this.btnData.map(item => {
if (item.v_if && item.v_noBtn) {
if (item.v_if(this.scope.row, this.scope) && this.permissionJudge(item.v_noBtn))arr.push(item);
} else if (item.v_if && !item.v_noBtn) {
if (item.v_if(this.scope.row, this.scope))arr.push(item);
} else if (!item.v_if && item.v_noBtn) {
if (this.permissionJudge(item.v_noBtn))arr.push(item);
} else {
arr.push(item);
}
})
if (arr.length > this.option.showNum && this.option.isHidden) {
this.data = [arr.slice(0, this.option.showNum), arr.slice(this.option.showNum)];
} else {
this.data = [arr];
}
},
permissionJudge(value) {
let authMenu = this.$store.getters.authMenu;// 獲取所有一級目錄
for (let item of authMenu) {
if (item.keyWord === value) {
return true;
}
}
return false;
}
},
beforeDestroy() {
// eslint-disable-next-line no-undef
$('.buttonSet_style').remove()
}
}
</script>
<style lang="stylus">
.buttonSet_style{
padding:10px 0;
}
.button-set-box .s-dropdown-item:hover > i{
color #fff!important
}
// .buttonSet_style{
// padding:6px 8px;
// color: #199FED;//#6da0cb
// background:#fff;//#19232e;
// .popper-arrow:after{
// border-left-color:#fff !important;
// }
// .iconfont{
// font-size: 20px;
// cursor:pointer;
// margin:0 2px;
// }
// }
</style>
到此這篇關(guān)于element中table操作按鈕展示與折疊的實現(xiàn)示例的文章就介紹到這了,更多相關(guān)element table按鈕展示折疊內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于vue+ bootstrap實現(xiàn)圖片上傳圖片展示功能
這篇文章主要介紹了基于vue+ bootstrap實現(xiàn)圖片上傳圖片展示功能,需要的朋友可以參考下2017-05-05
vue 組件之間事件觸發(fā)($emit)與event Bus($on)的用法說明
這篇文章主要介紹了vue 組件之間事件觸發(fā)($emit)與event Bus($on)的用法說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07
vue-cli 目錄結(jié)構(gòu)詳細講解總結(jié)
這篇文章主要介紹了vue-cli 目錄結(jié)構(gòu)詳細講解總結(jié),詳細的介紹了整個項目的目錄以及目錄文件的用法,非常具有實用價值,需要的朋友可以參考下2019-01-01
Vue?warn:Property?"state"?was?accessed?during
這篇文章主要為大家介紹了Vue?warn:Property?"state"?was?accessed?during?render的報錯解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-06-06
Vue移動端實現(xiàn)pdf/excel/圖片在線預覽
這篇文章主要為大家詳細介紹了Vue移動端實現(xiàn)pdf/excel/圖片在線預覽功能的相關(guān)方法,文中的示例代碼講解詳細,有需要的小伙伴可以參考下2024-04-04
詳解vue-cli本地環(huán)境API代理設(shè)置和解決跨域
這篇文章主要介紹了詳解vue-cli本地環(huán)境API代理設(shè)置和解決跨域,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-09-09

