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組件樣式的限制導致按鈕的展示與隱藏彈出框不能超過當前列長度。超出了就隱藏。這個問題本來是想設置定位來實現(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,//是否開啟操作欄隱藏設置,默認開啟 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實現(xiàn)下拉框的多選功能(附后端處理參數(shù))
本文介紹了如何使用Vue實現(xiàn)下拉框的多選功能,實現(xiàn)了在選擇框中選擇多個選項的功能,文章詳細介紹了實現(xiàn)步驟和示例代碼,對于想要了解如何使用Vue實現(xiàn)下拉框多選功能的讀者具有一定的參考價值2023-08-08Vue數(shù)據(jù)更新但頁面沒有更新的多種情況問題及解決
這篇文章主要介紹了Vue數(shù)據(jù)更新但頁面沒有更新的多種情況問題及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07elementplus?中?DatePicker?日期選擇器樣式修改無效的問題及解決方案
這篇文章主要介紹了elementplus中DatePicker日期選擇器樣式修改無效的問題,DatePicker日期選擇器彈出面板默認掛載在body上,所以在組件中添加了?scoped?屬性的?style?標簽下是修改不到其樣式的,講解了datepicker的使用方法,及常見的配置項和對應的值,需要的朋友可以參考下2024-01-01vue通過子組件修改父組件prop的多種實現(xiàn)方式
這篇文章主要介紹了vue通過子組件修改父組件prop的幾種實現(xiàn)方式,比較常用的方式是通過Prop單向傳遞的規(guī)則,需要的朋友可以參考下2021-09-09