2019-09-17 vue项目中将element-ui table表格写成组件

表格中我们经常需要动态加载数据, 如果有多个页面都需要用到表格, 那我希望可以有个组件, 只传数据过去显示, 不用每个页面都去写这么一段内容:

<el-table :data="tableData"  border size="mini" fit highlight-current-row height="500">
    <el-table-column type="index" align="center" fixed></el-table-column>
    <el-table-column prop="DHM" min-width="140px" label="时间" align="center"></el-table-column>
    <el-table-column prop="PLAZANO" min-width="100px" label="编码" align="center"></el-table-column>
    <el-table-column prop="PLAZANAME"  min-width="100px" label="名称" align="center"></el-table-column>
    <el-table-column prop="CAR_PLATE" label="号码" align="center"></el-table-column>
    <el-table-column prop="CARD_NO" min-width="120px" label="卡号" align="center"></el-table-column>
    <el-table-column prop="DATATYPE" label="数据类型" align="center" :formatter="formatDATATYPE"></el-table-column>
    <el-table-column prop="STAFFNAME" min-width="100px" label="姓名" align="center"></el-table-column>
    <el-table-column prop="MEDIATYPE" label="付款方式" align="center"></el-table-column>
    <el-table-column prop="COMP_CASH" label="计算费额" align="center"></el-table-column>
    <el-table-column prop="FACT_CASH" label="实收费额" align="center"></el-table-column>
    <el-table-column label="操作" min-width="140px" align="center">
       <template slot-scope="scope">
          <el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button>
          <el-button type="text" size="small">编辑</el-button>
       </template>
    </el-table-column>
</el-table>

上面这段代码是一个element-ui中tabele表格的形式,这里表头都是已经固定的, 如果每个页面都写上这么一段, 不同的是表头名字和字段,这样子就有点重复,而且页面的篇幅也就比较大了,于是把这块写成一个组件, 每个页面引入这个组件, 再传入数据。

1. 表格组件:

首先 table.vue 组件可以这样写:

<el-table :data="tableData"  border size="mini" fit highlight-current-row height="500" :row-style="rowStyle" @row-dblclick="rowDblclick"
      v-loading="loading"
      element-loading-text="拼命加载中"
      element-loading-spinner="el-icon-loading"
      element-loading-background="rgba(0, 0, 0, 0.3)">
      <el-table-column type="index" align="center" fixed></el-table-column>
      <!-- prop: 字段名name, label: 展示的名称, fixed: 是否需要固定(left, right), minWidth: 设置列的最小宽度(不传默认值), oper: 是否有操作列
           oper.name: 操作列字段名称, oper.clickFun: 操作列点击事件, formatData: 格式化内容 -->
      <el-table-column v-for="(th, key) in tableHeader"
        :key="key"
        :prop="th.prop"
        :label="th.label"
        :fixed="th.fixed"
        :min-width="th.minWidth" align="center">
          <!-- 加入template主要是有操作一栏, 操作一栏的内容是相同的, 数据不是动态获取的,不过我这里操作一栏的名字定死了(oper表示是操作这一列,否则就不是) -->
          <template slot-scope="scope">
            <div v-if="th.oper">
              <el-button v-for="(o, key) in th.oper" :key="key" @click="o.clickFun(scope.row)" type="text" size="small">{{o.name}}</el-button>
            </div>
            <div v-else>
              <span v-if="!th.formatData">{{ scope.row[th.prop] }}</span>
              <span v-else>{{ scope.row[th.prop] | formatters(th.formatData) }}</span>
            </div>
          </template>
      </el-table-column>
</el-table>
// 这里是传入的数据 
props: {
    tableData: {
      type: Array,
      default: function () {
        return []
      }
    },
    rowDblclick: {
      type: Function,
      default: (row, event, column) => { console.log('default: ' + row + '---' + event + '---' + column) }
    },
    tableHeader: {
      type: Array,
      default: function () {
        return []
      }
    },
    loading: {
      type: Boolean,
      default: false
    }
  },

然后在其他组件中就可以引入table组件, 将数据传给table显示

<table :tableData="tableData" :rowDblclick="rowDblclick" :tableHeader="tableHeader" :loading="loading"></table>

其中 tableData是表格中要显示的数据内容, 这个内容我的是从后台查询出来的, rowDblclick 是双击一行做的操作,如果不需要可以删除, tableHeader 是表头显示的数据, loading 是表格加载的loading方式, 默认是没有的

表头数据格式如下: formatData 是表格里面的数据需要做处理的方法, oper是操作列,查看和编辑是两个按钮,handleClick和editClick点击按钮的方法, 自行补充。

export const tableHeader = [ // 表头数据
  { prop: 'dhm', label: '时间', minWidth: '140px' },
  { prop: 'plazano', label: '编码', minWidth: '100px' },
  { prop: 'plazano', label: '名称', minWidth: '100px', formatData: val => store.getters.allPlazano2Map.get(val) },
  { prop: 'car_plate', label: '号码' },
  { prop: 'card_no', label: '卡号', minWidth: "120px" },
  { prop: 'laneno', label: '数据类型', formatData: function(val) { return val.substr(2, 1) == '1' ? '出口' : '入口' } },
  { prop: 'staffname', label: '姓名', minWidth: '100px' },
  { prop: 'mediatype', label: '付款方式' },
  { prop: 'comp_cash', label: '计算费额' },
  { prop: 'fact_cash', label: '实收费额' },
  { prop: 'oper', label: '操作', fixed: 'right', minWidth: '140px',
    oper: [
      { name: '查看', clickFun: handleClick },
      { name: '编辑', clickFun: editClick }
    ]
  }
]

现在的代码可能会报错, 下面这处的代码是在全局注册了一个过滤器,如果不注册就找不到这个方法就会报错,所以还需要注册一个全局过滤器,如果你不需要对数据做处理可以不要这个过滤器

image

2. 注册全局过滤器, 我的是这样写的, 先新建个文件 filter.js 然后在里面写个方法, export 出去

export function formatters(val, format) {
   if (typeof (format) === 'function') {
     return format(val)
   } else return val
}

然后再在main.js中引入进来注册全局的过滤器:

import * as filters from './filters'
 
Object.keys(filters).forEach(key => {
   Vue.filter(key, filters[key])
})

这个在每个页面就都可以使用 formatters 这个过滤器方法了, 不过具体的过滤方法是由 format 这个参数传进去的, 这里主要是因为不同的数据过滤的方法不一样, 所以在表头传数据的时候就一并写上处理数据的方法

image

如果很多地方都使用了同一个方法, 可以将这个方法注册成全局方法, 那么在每个页面就可以直接使用该方法, 不用重复去写。

3. 注册全局方法

建立个js 文件(我的文件名为validate.js), 写入该方法, 这里使用 exports.install 注册全局方法,挂载到vue原型上

exports.install = (Vue, options) => {
  Vue.prototype.validator = {
    lanenoTransf(val) { return val.substr(2, 1) == '1' ? '出口' : '入口' }
  }
}

然后在main.js中引入

import validator from '@/utils/validate'

Vue.use(validator)

最后页面上就可以直接使用

{ prop: 'laneno', label: '数据类型', formatData: this.lanenoTransf },
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,193评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,306评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,130评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,110评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,118评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,085评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,007评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,844评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,283评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,508评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,395评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,985评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,630评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,797评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,653评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,553评论 2 352

推荐阅读更多精彩内容