element中table操作按钮展示与折叠的实现示例

作者:My_Bells 时间:2024-05-02 16:35:35 

先来看实现效果。

element中table操作按钮展示与折叠的实现示例

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>

@/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>

来源:https://blog.csdn.net/qwe435541908/article/details/103242502

标签:element,table,按钮
0
投稿

猜你喜欢

  • python GUI库图形界面开发之PyQt5布局控件QGridLayout详细使用方法与实例

    2023-08-29 03:43:39
  • 如何列举Error的所有对象?

    2010-01-12 20:01:00
  • HTML5 Canvas 起步(1) - 基本概念

    2009-04-21 13:14:00
  • python使用sessions模拟登录淘宝的方式

    2023-01-09 12:05:25
  • PHP和NodeJs开发的应用如何共用Session

    2024-06-05 09:43:22
  • sqlserver中根据字符分割字符串的最好的写法分享

    2012-06-06 19:44:40
  • Python 字符串去除空格的五种方法

    2023-01-15 08:23:56
  • Python如何匹配文本并在其上一行追加文本

    2022-10-19 13:16:43
  • python3实现zabbix告警推送钉钉的示例

    2023-01-16 06:59:04
  • MySQL里面的子查询实例

    2024-01-14 20:43:17
  • 使IE浏览器支持PNG格式图片的透明效果

    2008-02-02 16:20:00
  • vue调用高德地图实例代码

    2024-06-07 15:20:47
  • Python使用jpype模块调用jar包过程解析

    2023-04-12 03:07:12
  • mysql存储过程如何利用临时表返回结果集

    2024-01-13 07:39:05
  • asp 输出换行的详细说明 原创

    2011-02-24 11:15:00
  • 试了下Golang实现try catch的方法

    2023-07-21 20:49:59
  • 算法系列15天速成 第四天 五大经典查找【上】

    2023-12-18 01:20:38
  • MySQL 实现双向复制的方法指南

    2024-01-27 02:19:51
  • python处理文本文件实现生成指定格式文件的方法

    2022-01-07 21:41:43
  • vue3.0使用mapState,mapGetters和mapActions的方式

    2023-07-02 16:49:56
  • asp之家 网络编程 m.aspxhome.com