element-ui 二次封装表格以及添加、编辑dialog

1、table 组件以及弹窗组件

<!--表格组件 -->
<template>
<section class="ces-table-page">
  <!-- 表格操作按钮 -->
    <section class="ces-handle" v-if='isHandle'>
      <el-button 
        v-for='(item,index) in tableHandles' 
        :key="index" 
        :size="item.size || size" 
        :type="item.type" 
        :icon='item.icon' 
        @click="item.handle()">
          {{item.label}}
      </el-button>
    </section>
    <!-- 数据表格 -->
    <section class="ces-table">
      <el-table 
        :data='tableData' 
        :size='size' 
        height="100%" 
        :cell-style="{textAlign: 'center'}"
        :header-cell-style="{textAlign: 'center', color: '#333', background: '#F5F7FA'}"
        :border='isBorder'
        @select='select' 
        @select-all='selectAll'
        @row-click="handleRowClick"
        :defaultSelections="defaultSelections"
        v-loading='loading' 
        ref="cesTable">
          <el-table-column v-if="isSelection" type="selection" align="center" ></el-table-column>
          <el-table-column v-if="isIndex" type="index" :label="indexLabel" align="center" width="50"></el-table-column>
          <!-- 数据栏 -->
          <el-table-column v-for="item in tableCols" 
            :key="item.id"
            :prop="item.prop" 
            :label="item.label" 
            :width="item.width"
            :align="item.align" 
            :render-header="item.require?renderHeader:null"
            >
              <template slot-scope="scope" >
                <!-- html -->
                <span v-if="item.type==='Html'" v-html="item.html(scope.row)"></span>
                <!-- 按钮 -->
                <span v-if="item.type==='Button'" >
                  <el-button v-for="(btn, index) in item.btnList" 
                    :key="index"
                    v-if="!btn.isShow || (btn.isShow && btn.isShow(scope.$index, scope.row))"
                    :disabled="btn.isDisabled && btn.isDisabled(scope.$index, scope.row)"
                    :type="btn.type" 
                    :size="btn.size || size" 
                    :icon="btn.icon" 
                    @click="btn.handle(scope.row)">{{btn.label}}</el-button>
                  </span>
                <!-- 输入框 -->
                <el-input v-if="item.type==='Input'" v-model="scope.row[item.prop]" :size="size" 
                  :disabled="btn.isDisabled && btn.isDisabled(scope.row)"
                  @focus="item.focus && item.focus(scope.row)"></el-input>
                <!-- 下拉框 -->
                <el-select v-if="item.type==='Select'" v-model="scope.row[item.prop]" :size="size" :props="item.props"
                  :disabled="btn.isDisabled && btn.isDisabled(scope.row)" 
                  @change='item.change && item.change(scope.row)'>
                    <el-option v-for="op in item.options" :label="op[item.props.label]" :value="op[item.props.value]" :key="op[item.props.value]"></el-option>
                </el-select>
                <!-- 单选 -->
                <el-radio-group v-if="item.type==='Radio'" v-model="scope.row[item.prop]"
                  :disabled="btn.isDisabled && btn.isDisabled(scope.row)"
                  @change='item.change && item.change(scope.row)'>
                    <el-radio v-for="(ra,index) in item.radios" :key="index" :label="ra.value">{{ra.label}}</el-radio>
                </el-radio-group>
                <!-- 复选框 -->
                <el-checkbox-group v-if="item.type==='Checkbox'" v-model="scope.row[item.prop]" 
                  :disabled="btn.isDisabled && btn.isDisabled(scope.row)"
                  @change='item.change && item.change(scope.row)'>
                    <el-checkbox v-for="(ra,index) in item.checkboxs" :key="index" :label="ra.value">{{ra.label}}</el-checkbox>
                </el-checkbox-group>
                <!-- 评价 -->
                <el-rate v-if="item.type==='Rate'" v-model="scope.row[item.prop]"
                  :disabled="btn.isDisabled && btn.isDisabled(scope.row)"
                  @change='item.change && item.change(scope.row)'></el-rate>
                <!-- 开关 -->
                <el-switch v-if="item.type==='Switch'" v-model="scope.row[item.prop]"
                  :disabled="btn.isDisabled && btn.isDisabled(scope.row)"
                  @change='item.change && item.change(scope.row)'></el-switch>
                <!-- 图像 -->
                <img v-if="item.type==='Image'" :src="scope.row[item.prop]" @click="item.handle && item.handle(scope.row)"/>
                <!-- 滑块 -->
                <el-slider v-if="item.type==='Slider'" v-model="scope.row[item.prop]" 
                :disabled="btn.isDisabled && btn.isDisabled(scope.row)"
                  @change='item.change && item.change(scope.row)'></el-slider>
                <!-- 默认 -->
                <span v-if="!item.type" 
                  :style="item.itemStyle && item.itemStyle(scope.row)" 
                  :class="item.itemClass && item.item.itemClass(scope.row)">{{(item.formatter && item.formatter(scope.row)) || scope.row[item.prop]}}</span>
              </template>
            </el-table-column>
      </el-table>
    </section>
    <!-- 分页 -->
    <section class="ces-pagination"  v-if='isPagination'>
      <el-pagination style='display: flex;justify-content: center;height: 100%;align-items: center;'
        @current-change="handleCurrentChange"
        @size-change="handleSizeChange"
        layout="total,sizes ,prev, pager, next,jumper"
        :page-sizes="[5, 10, 15, 20]"
        :page-size="pagination.pageSize"
        :current-page="pagination.pageNum"
        :total="pagination.total"
      ></el-pagination>
    </section>
</section>
</template>

<script>

export default {
  props:{
    // 表格型号:mini,medium,small
    size:{ type: String, default: 'medium' },
    isBorder:{ type: Boolean, default: true },
    loading:{ type: Boolean, default: false },
    // 表格操作
    isHandle:{ type: Boolean, default: false },
    tableHandles:{ type: Array, default:()=>[] },
    // 表格数据
    tableData:{ type: Array, default:()=>[] },
    // 表格列配置
    tableCols:{ type: Array, default:()=>[] },
    // 是否显示表格复选框
    isSelection:{ type: Boolean, default: false },
    defaultSelections:{ type: [Array,Object], default:()=>null },
    // 是否显示表格索引
    isIndex:{ type: Boolean, default: false },
    indexLabel: { type: String, default:'序号' },
    // 是否显示分页
    isPagination:{ type: Boolean, default: true },
    // 分页数据
    pagination:{ type: Object, default:()=>({pageSize:5,pageNum:1,total:0}) },
    
  },
  data(){
    return {
    }
  },
  watch:{
    'defaultSelections'(val) {
      this.$nextTick(function(){
        if(Array.isArray(val)){
          val.forEach(row=>{
            this.$refs.cesTable.toggleRowSelection(row)
          })
        }else{
          this.$refs.cesTable.toggleRowSelection(val)
        }
      })      
    }
  },
  methods:{
    // 表格勾选
    select(rows,row){
      this.$emit('select',rows,row);
    },
    // 全选
    selectAll(rows){
      this.$emit('select',rows)
    },
    // 点击行选中
    handleRowClick(row, col, event) {
      this.$emit('select',row)
      this.$refs.cesTable.toggleRowSelection(row)
    },
    // 
    handleCurrentChange(val){
      this.pagination.pageNum = val;
      this.$emit('refresh');
    },
    handleSizeChange(val) {
      this.pagination.pageSize = val;
      this.$emit('refresh');
    },
    
    // tableRowClassName({rowIndex}) {
    //     if (rowIndex % 2 === 0) {
    //         return "stripe-row";
    //     }
    //     return "";
    // }
    renderHeader(h,obj) {
      return h('span',{class:'ces-table-require'},obj.column.label)
    },
  },
}
</script>
<style>
.ces-handle {
  margin-bottom: 10px;
}
.ces-pagination {
  margin-top: 18px;
}
.ces-table-require::before{
  content:'*';
  color:red;
}
</style>

3、弹窗组件

<template>
    <div class="dialog-container">
        <el-dialog
            :title="dialogDatas.title"
            :width="dialogDatas.width"
            :visible.sync="visible"
            @close="$emit('updateShow', false)"
            :show="show">
            <!-- <span>this is a dialog.</span> -->
            <slot></slot>
            <span slot="footer" class="dialog-footer">
                <el-button @click="visible = false">取 消</el-button>
                <el-button type="primary" @click="visible = false">确 定</el-button>
            </span>
        </el-dialog>
    </div>
</template>

<script>
    export default {
        data () {
            return {
                visible: this.show
            };
        },
        props: {
            show: {
                type: Boolean,
                default: false
            },
            dialogDatas: {
                type: Object,
                required: true
            }
        },
        watch: {
            show () {
                this.visible = this.show;
            }
        }
    };
</script>

2、在组件中调用

<template>
    <div>
        <xy-table 
            size='mini'
            :isSelection='true'
            :isIndex='true'
            :isPagination='true'
            :isHandle='true'
            :tableData='tableData' 
            :tableCols='tableCols' 
            :tableHandles='tableHandles'
            :pagination='pagination'
            @refresh="refresh"
            @select="select"
        >
        </xy-table>


        <!-- 弹窗 -->
        <xy-modal :show.sync="show" :dialogDatas="dialogDatas" @updateShow="dialogShow">
            <xy-edit ref='xyEdit' :that='that' 
                :editCfg='editForm' 
                :editData='editData' 
                :editRules='editRules' >
            </xy-edit>
        </xy-modal>
    </div>
</template>

<script>
import xyTable from '@/components/common/Table/xyTable'
import xyModal from '@/components/common/Modal/xyModal'
import xyEdit from '@/components/common/Form/addOrEditForm'

let sexs=[{label:'男',value:'M'},{label:'女',value:'F'}]
let sexProps={label:'label',value:'value'}
let intersts=[{label:'羽毛球',value:'badminton'},{label:'篮球',value:'basketball'},{label:'足球',value:'football'},{label:'兵乓球',value:'pong'}]
let interstProps={label:'label',value:'value'}
export default {
    components: {
        xyTable,
        xyModal,
        xyEdit
    },
    data() {
        // let sexs=[{label:'男',value:'M'},{label:'女',value:'F'}]
        // let sexProps={label:'label',value:'value'}
        // let intersts=[{label:'羽毛球',value:'badminton'},{label:'篮球',value:'basketball'}]
        // let interstProps={label:'label',value:'value'}
        return {
            show: false,

            tableData:[
                {name:'张三',age:'12',sex:'男',interst:'篮球'},
                {name:'筱华',age:'27',sex:'女',interst:'羽毛球'},
                {name:'张三',age:'12',sex:'男',interst:'篮球'},
                {name:'筱华',age:'27',sex:'女',interst:'足球'},
                {name:'筱华',age:'27',sex:'女',interst:'羽毛球'},
                {name:'筱华',age:'27',sex:'女',interst:'兵乓球'},
                {name:'筱华',age:'27',sex:'女',interst:'羽毛球'}
            ],
            tableCols:[
                {label:'姓名',prop:'name'},
                {label:'年龄',prop:'age'},
                {label:'性别',prop:'sex'},
                {label:'爱好',prop:'interst'},
                {label:'操作',type:'Button',btnList:[
                    {isShow: (index,row) => this.showEdit(index,row),isDisabled: (index,row) => this.disabledBtn(index,row), type:'primary',label:'编辑',handle:row=>this.edit(row)},
                    {type:'danger',label:'删除',handle:row=>''}
                ]}
            ],
            tableHandles:[
                {label:'新增',type:'primary',handle:row=>this.addDatas()}
            ],
            pagination:{
                pageSize:5,
                pageNum:1,
                total:7
            },
            dialogDatas: {
                title: '新增', // 新增或编辑
                width: '500px' // dialog 宽度
            },
            that: this,

            editForm: [
                {label: '姓名', prop: 'name', type: 'input', width: '280px', change: data=> console.log(data)},
                {label: '年龄', prop: 'age', type: 'input', width: '280px'},
                {label: '性别', prop: 'sex', type: 'radio', radios: sexs, width: '280px'},
                {label: '爱好', prop: 'interst', type: 'checkbox', checkboxs: intersts, width: '280px'},
            ],
            // 编辑表单的数据
            editData: {
                name: null,
                age: null,
                sex: null,
                interst: []
            },
            // 表单验证
            editRules: {
                name: [{requied: true, message: '请输入姓名', trigger: 'blur'}]
            }
        }
    },
    methods: {
        showEdit(index,row) {
            return true
        },
        disabledBtn(index,row) {
            if (index == 0) {
                return true
            }
        },
        dialogShow() {
            this.show = false
        },
        addDatas() {
            this.show = true
            this.dialogDatas.title = '新增'
            for (let k of Object.keys(this.editData)) {
                if (k == 'interst') {
                    this.editData[k] = []
                } else {
                    this.editData[k] = null
                }
            }
            console.log(this.editData)
        },
        edit(row) {
            this.show = true
            let editRow = JSON.parse(JSON.stringify(row))
            this.dialogDatas.title = '编辑'
            if (editRow.sex == '女') {
                editRow.sex = "F"
            } else {
                editRow.sex = "M"
            }
            console.log(editRow)
            let interstArr = intersts.filter(function(product){
                return product.label === editRow.interst
            })
            editRow.interst = [interstArr[0].value]
            this.editData = editRow
        },
        refresh() {
            console.log('翻页')
        },
        select(rows, row) {
            console.log(rows, row)
        }
    }
}
</script>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,898评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,401评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,058评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,539评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,382评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,319评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,706评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,370评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,664评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,715评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,476评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,326评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,730评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,003评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,275评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,683评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,877评论 2 335