VUE 对element-ui中的ElTableColumn扩展

公司有一个新的需求,点击ElTableColumn的头部可以进行搜索,这个功能同事已经做出来了,但是使用有些不方便,自己就打算封装成一个组件,学习一下。

ElTableColumn本来是这个样子的:

elemnet table.png

要做成的是这个样子:

gif.gif

我直接就放代码了,挨着挨着说明太多了。
新版本在下面

代码的结构:

代码结构.png

组件

<!--  ElTableColumnPro.vue  -->


<template>
      <el-table-column v-if="visible" :formatter="formatter"  :align='align' :prop="prop" :header-align="headerAlign" :label="label" :width="width" :render-header="renderHeader" >
          <template  slot-scope="scope">
            <slot :row="scope.row" :$index="scope.$index" >
              <span>{{fomatMethod(scope.row[prop])}}</span>
            </slot>
          </template>
      </el-table-column>
</template>

<script>
import moment from "moment";

export default {
  name: "el-table-column-pro",
  props: {
    prop: {
      type: String
    },
    label: {
      type: String
    },
    width: {
      type: Number
    },
    renderType: {
      type: String,
      validator: value => ["date", "input", "select"].includes(value)
    },
    placeholder: {
      type: String
    },
    rederWidth: {
      type: String,
      default: "230px"
    },
    param: {
      type: String,
      default: ""
    },
    startDate: {
      type: String
    },
    endDate: {
      type: String
    },
    selectList: {
      type: Array
    },
    isClear: {
      type: Boolean,
      default:true
    },
    visible: {
      type: Boolean,
      default: true
    },
    filterIcon: {
      type: String,
      default: "el-icon-search"
    },
    callback: {
      type: Function
    },
    formatter: {
      type: Function,
      default:(row, column, cellValue)=>cellValue
    },
    align:{
      type:String 
    },
    headerAlign:{
      type:String
    }
  },
  data() {
    return {
      formatD:this.filterIcon
    };
  },
 
  methods: {

    fomatMethod(value){
      return this.formatter('','',value)
    },
   
    renderHeader(createElement, { column, $index }) {
      switch (this.renderType) {
        case "date":
          return this.renderDate(createElement, { column, $index });

        case "input":
          return this.rederInput(createElement, { column, $index });
         
        case "select":
          return this.rederSelect(createElement, { column, $index });
       
        default:
          return column.label;
      }
    },

    rederInput(createElement, { column, $index }) {
      return createElement(
        "div",
        {
          class: "filters",
          style: {
            color: column.color
          }
        },
        [
          createElement(
            "el-popover",
            {
              props: {
                placement: "bottom",
                width: "200",
                trigger: "click"
              }
            },
            [
              createElement("el-input", {
                props: {
                  placeholder: this.placeholder,
                  value: this.param
                },
                nativeOn: {
                  keyup: event => {
                    if (event.keyCode === 13) {
                      this.$emit("update:param", event.target.value);
                      this.callback && this.callback();
                    }
                  }
                },
                on: {
                  blur: event => {
                    this.$emit("update:param", event.target.value);
                    this.callback && this.callback();
                  }
                }
              }),
              createElement(
                "span",
                {
                  slot: "reference"
                },
                [
                  column.label,
                  createElement("i", {
                    class: this.filterIcon,
                    style: {
                      marginLeft: "4px"
                    }
                  })
                ]
              )
            ]
          )
        ]
      );
    },

    rederSelect(createElement, { column, $index }) {
      return createElement(
        "div",
        {
          class: "filters",
          style: {
            color: column.color
          }
        },
        [
          createElement(
            "el-popover",
            {
              props: {
                placement: "bottom",
                width: "200",
                trigger: "click"
              }
            },
            [
              createElement(
                "el-select",
                {
                  props: {
                    placeholder: this.placeholder,
                    value: this.param,
                    clearable: this.isClear
                  },
                  on: {
                    input: value => {
                      this.$emit("update:param", value);
                      this.callback && this.callback();
                    }
                  }
                },
                [
                  this.selectList.map(item => {
                    return createElement("el-option", {
                      props: {
                        value: item.value,
                        label: item.label
                      }
                    });
                  })
                ]
              ),
              createElement(
                "span",
                {
                  slot: "reference"
                },
                [
                  column.label,
                  createElement("i", {
                    class: this.filterIcon,
                    style: {
                      marginLeft: "4px"
                    }
                  })
                ]
              )
            ]
          )
        ]
      );
    },

    renderDate(createElement, { column, $index }) {
      return createElement(
        "div",
        {
          class: "filters"
        },
        [
          createElement(
            "el-popover",
            {
              props: {
                placement: "bottom",
                width: this.rederWidth,
                trigger: "click"
              }
            },
            [
              createElement("el-date-picker", {
                props: {
                  placeholder: this.placeholder,
                  value: this.value,
                  type: "daterange",
                  rangeSeparator:"至",
                  startPlaceholder:"开始日期",
                  endPlaceholder:"结束日期",
                },
                style: {
                  width: this.rederWidth
                },
                on: {
                  input: value => {
                    if (value) {
                      const startDate = moment(value[0]).format("YYYY-MM-DD");
                      const endDate = moment(value[1]).format("YYYY-MM-DD");
                      this.$emit("update:startDate", startDate);
                      this.$emit("update:endDate", endDate);
                      this.callback && this.callback();
                    }
                  }
                }
              }),
              createElement(
                "span",
                {
                  slot: "reference"
                },
                [
                  column.label,
                  createElement("i", {
                    class: this.filterIcon,
                    style: {
                      marginLeft: "4px"
                    }
                  })
                ]
              )
            ]
          )
        ]
      );
    }
  }
};
</script>

新版本的实现

这个版本里面直接用了dayjs处理了时间,如果不需要处理,直接去掉对应的地方就可。还有pug,可以直接转,网上有在线的工具。

<template lang='pug'>
    el-table-column(:align="align", :prop="prop", :header-align="headerAlign", :label="label", :width="width", :fixed="fixed", v-if='show')
        template(slot="header", slot-scope="scope")
            el-popover.popover(:disabled="!renderType", placement="bottom-start", :ref="'popover'+scope.$index", :width="renderWidth", trigger="click")
                el-input(v-show="renderType === 'input'" ,v-model="value", @change="handlerInput", :placeholder="placeholder")
                el-select(v-show="renderType === 'select'", :isClear="isClear", @change="handlerSelect", v-model="value", :placeholder="placeholder")
                    el-option(:label="item.label", :value="item.value", :key="item.value", v-for="item in selectList")

                el-date-picker(v-show="renderType === 'date'", v-model="value", @change="handlerDate", type="date", :width="renderWidth", :placeholder="placeholder")
                el-date-picker(v-show="renderType === 'datetime'", v-model="value", @change="handlerDate", type="daterange", range-separator="至", start-placeholder="开始日期", end-placeholder="结束日期")
                div(slot="reference",  :class="renderType?'popover-ref':''", :style="color")
                    span {{label}}
                    i(v-show="renderType", :class="filterIcon")

        template(slot-scope="scope")
            slot(:row="scope.row", :$index="scope.$index")
                el-tooltip(:content="formatter(scope.row,scope.row[prop])",placement="top", v-show='isMore')
                    span.ellipsis {{scope.row[prop] | substring}}
                span.ellipsis(v-show='!isMore') {{formatter(scope.row,scope.row[prop])}}
</template>
<script>
    import moment from 'dayjs'

    export default {
        name: "el-table-column-pro",
        props: {
            fixed: {
                type: String,
                default: null
            },
            prop: {
                type: String
            },
            label: {
                type: String
            },
            width: {
                type: Number
            },
            renderType: {
                type: String,
                validator: value => ['date', 'input', 'select', 'datetime'].includes(value)
            },
            placeholder: {
                type: String
            },
            renderWidth: {
                type: String,
                default: '350px'
            },
            param: {
                type: String,
                default: ''
            },
            startDate: {
                type: String
            },
            endDate: {
                type: String
            },
            selectList: {
                type: Array
            },
            isClear: {
                type: Boolean,
                default: true
            },
            visible: {
                type: Boolean,
                default: true
            },
            filterIcon: {
                type: String,
                default: 'el-icon-search'
            },
            callback: {
                type: Function
            },
            formatter: {
                type: Function,
                default: (row,cellValue) => cellValue?cellValue.toString():''
            },
            align: {
                type: String,
                default:'center'
            },
            headerAlign: {
                type: String,
                default:'center'
            },
            page: {
                type: Number
            },
            isMore: {
                type: Boolean,
                default: false
            }
        },
        filters: {
            substring(value){
                if(value){
                   if(value instanceof  String){
                       return `${value.substring(0,10)}...`
                   }
                   return value
                }
                return ''
            }
        },
        watch: {
            'param'(val) {
                this.value = val
                this.color = val ? 'color:#20a0ff' : ''
            },
            'startDate'(val) {
                this.color = val ? 'color:#20a0ff' : ''
                this.value[0] = new Date(val)
            },
            'endDate'(val) {
                this.color = val ? 'color:#20a0ff' : ''
                this.value[1] = new Date(val)
            }
        },
        data() {
            return {
                value: this.startDate || this.endDate ? [new Date(this.startDate), new Date(this.endDate)] : this.param,
                color: this.param || this.startDate || this.endDate ? 'color:#20a0ff' : '',
                show: this.visible
            }
        },

        methods: {
            toggle(visible) {
                this.show = visible
            },
            handlerInput(value) {
                this.$emit('update:param', value)
                this.$emit('update:page', 0)
                this.color = value ? 'color:#20a0ff' : ''
                this.callback()
            },
            handlerSelect(value) {
                this.$emit('update:param', value)
                this.$emit('update:page', 0)
                this.color = value ? 'color:#20a0ff' : ''
                this.callback()
            },
            handlerDate(value) {
                if (value) {
                    if (this.renderType === 'date') {
                        this.$emit('update:param', moment(value).format('YYYY-MM-DD'))
                        this.$emit('update:page', 0)
                        this.color = value ? 'color:#20a0ff' : ''
                        this.callback()
                    } else {
                        this.color = value ? 'color:#20a0ff' : ''
                        const startDate = moment(value[0]).format('YYYY-MM-DD')
                        const endDate = moment(value[1]).format('YYYY-MM-DD')
                        this.$emit('update:param', startDate + '~' + endDate)
                        this.$emit('update:startDate', startDate)
                        this.$emit('update:endDate', endDate)
                        this.$emit('update:page', 0)
                        this.callback()
                    }
                } else {
                    if (this.renderType === 'date') {
                        this.$emit('update:param', value)
                        this.$emit('update:page', 0)
                        this.color = value ? 'color:#20a0ff' : ''
                        this.callback()
                    } else {
                        this.color = value ? 'color:#20a0ff' : ''
                        this.$emit('update:param', '')
                        this.$emit('update:startDate', '')
                        this.$emit('update:endDate', '')
                        this.$emit('update:page', 0)
                        this.callback()
                    }
                }
            }
        }
    }
</script>
<style lang="stylus" scoped>
    .popover-ref {
        cursor: pointer;
        padding: 0;
    }

    .popover
        display flex
        justify-content center
        align-items center


</style>

<!--  index.js  -->


import ElTableColumnPro from './ElTableColumnPro'

ElTableColumnPro.install = function(Vue) {
  Vue.component(ElTableColumnPro.name, ElTableColumnPro);
};

export default ElTableColumnPro;

安装

import ElTableColumnPro from 'components/ElTableColumnPro/index' 
...
...
...

Vue.use(ElTableColumnPro)

使用

 <el-table :data="bankFlow" style="width:100%" stripe>
        <el-table-column-pro :visible="showMore"  prop="transactionId" label="流水号" :width="120"> </el-table-column-pro>
        <el-table-column-pro  prop="clientCode" label="客户代码 " :width="120" placeholder="请输入客户代码" :callback="requestTransactionLogs"  renderType="input" :param.sync="request_params.clientCode"> </el-table-column-pro>
        <el-table-column-pro  prop="eventTypeName" label="事件 " placeholder="请选择事件"   :selectList="listEventEnum" :callback="requestTransactionLogs"  renderType="select" :param.sync="request_params.event" :width="100">  </el-table-column-pro>
        <el-table-column-pro  prop="createTime" :callback="requestTransactionLogs" :startDate.sync="request_params.startDate" :endDate.sync="request_params.endDate" :formatter="$timeformat" label="时间" renderType="date" :width="180" ></el-table-column-pro>
 </el-table>
 <el-table :data="lists.content" v-loading="loading" @row-dblclick="detail"  >
        <el-table-column-pro :width="120" prop="clientCode" label="客户代码 " align="center" header-align="center" placeholder="请输入客户代码" :callback="getLists"  renderType="input" :param.sync="params.clientCode"></el-table-column-pro>           
        <el-table-column-pro label="内容 " placeholder="请输入内容" :callback="getLists"  renderType="input" :param.sync="params.content">
               <template slot-scope="scope">
                      <pre>{{scope.row.content}}</pre>
               </template>
        </el-table-column-pro>
        <el-table-column-pro prop="userName" :width="100" label="记录人 " align="center" header-align="center" placeholder="请输入记录人" :callback="getLists"  renderType="input" :param.sync="params.userName"></el-table-column-pro>
        <el-table-column prop="createTime" width="150" label="记录时间" align="center" header-align="center" :formatter="$dateTimeFormat"></el-table-column>
 </el-table>

注释就不挨着打了....

如果有问题,联系方式Q121116111,在的话就能看到。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容