vue+elementUI封装一个根据后端变化的动态table(完整代码)

实现了自动生成和插槽两个方式,主要把 el-table 和el-pagination封装在一起

效果图:

使用组件,启用自动生成 :auto="true"

自动生成-编辑 (包括请求已经实现了)新增和删除也是一样

ps:如有额外的按钮可以用插槽实现

查询的时候,只需要多返回下面数据,就可以自动生成列,和对应操作按钮

目录

table.vue

<template>
    <div>

      <el-row v-if="auto">
          <el-col :span="4">
           <el-button size="small" type="primary" @click="add(table.buttons.add)">新增</el-button>
           </el-col>
          <el-col :span="20">
            <div style="display: flex;justify-content: flex-end;margin:10px 0 10px 0">
                <slot name="search"></slot>
                <el-button size="small" type="primary" @click="filterData">查询</el-button>
            </div>
          </el-col>
        </el-row>
        <el-row v-else>
          <el-col :span="24" style="padding-top: 30px"> </el-col>
        </el-row>

    <el-table v-if="auto" v-loading="table.loading" :data="table.data" style="width: 100%">
        <el-table-column   v-for="(item,index) in table.columns" :key="index" :label="item.label+'-自动生成'" :prop="item.prop"></el-table-column>

        <el-table-column label="操作-自动生成">
             <template slot-scope="scope">
                <el-button  size="small" type="button" @click="edit(scope.row,table.buttons.edit)">编辑</el-button>
                <el-button  size="small" type="danger" @click="del(scope.row,table.buttons.del)">删除</el-button>
             </template>
        </el-table-column>
    </el-table>

    <el-table v-if="!auto" v-loading="table.loading" :data="table.data" style="width: 100%">
        <slot>
            <el-table-column label="默认列" ></el-table-column>
        </slot>
    </el-table>
    <el-pagination
            background
            :current-page="this.$parent.filters.pageIndex"
            layout="total, sizes, prev, pager, next, jumper"
            :page-size="this.$parent.filters.pageSize"
            style="width: 50%;margin:20px auto 0px auto;text-align: center;"
            :total="total"
            @current-change="handleCurrentChange"
            @size-change="handleSizeChange"
        />
    </div>
</template>
<script>

export default ({
    name:'table-test',
    props: {
        auto:{
            type:Boolean,
            default:()=>false,
        },
        query: {
            type: Function,
            default: ()=>null,
        },
    },
    created(){
        this.filterData()
    },
   data(){
    return {

        table:{
            columns:[],
            buttons:{},
            data:[],
            loading:false,
        },
        total:0
    }
   },
   methods:{
     handleCurrentChange(index) {
        this.$parent.filters.pageIndex = index
        this.filterData()
      },
     handleSizeChange() {},
     filterData(){
        this.table.loading=true
       /* eslint-disable */
        // debugger
        if(this.query){
            this.query().then(res=>{
                this.table.data = res.data
                this.table.columns =res.columns
                this.table.buttons =res.buttons
                this.total=res.totalCount
            }).finally(()=>{
                this.table.loading=false
            })
        }else{
            console.error('table组件未设置query函数')
        }
     },
    del(row,setting){
        // this.table.data.splice(index,1)
        this.$baseConfirm('你确定要删除吗?', null,  () => {
            this.fn(row,setting)
        })
    },
    add(setting){
        // 约定添加、编辑弹窗组件都叫 addIndex或者一个其它统一的名称, 就可以实现通用
        this.$parent.$refs.addIndex.show((form)=>this.fn(form,setting))
    },
    edit(row,setting){
         this.$parent.$refs.addIndex.showEdit(()=>this.fn(row,setting),row)
    },
    fn(row,setting){
        if(!row){
            throw 'fn:row is null'
        }
        Object.keys(setting.data).forEach(x=> {
          setting.data[x] =  row[x]
        })
         Object.keys(setting.param).forEach(x=> {
          setting.param[x] =  row[x]
        })
        this.request({
            url:setting.url,
            mtehod:setting.method,
            param:setting.param,
            data:setting.data
        }).then((res)=>{
            this.$message.success(res.message)
            this.filterData()
        })
    },
    //模拟请求
    request(param){
        console.log('request',param)
        return new Promise((res,rej)=>{
            setTimeout(() => {
                res({code:200,data:null,message:'ok'})
            }, 100);
        })
    }
   }
})
</script>
<style lang="scss" scoped>

table button{
    margin-top:10px;
}
::v-deep{
     .el-table .el-table__cell{
        padding:8px 0;
    }
    .el-table__cell .el-button:first-child{
        margin-left: 10px;
    }
}
</style>

index.vue

<template>
    <div id="app" style="width:1000px;background-color:cornsilk;margin:0 auto;padding:20px">
       <div style="margin-top: 150px"></div>

        <!-- 由后端接口返回的好处:
        接口参数有任何变化,接口名称变更,后端直接更新即可,不用前端修改 ,减少了来回沟通的成本
        组件提供了标准化,完整的基础功能,省去人为复制代码出现bug后修改的时间成本
        省去的基础功能实现的细节,减少了功能细节缺胳膊少腿后期修补的时间成本 -->
        <!-- 使用 auto="true" 根据接口返回的配置【自动生成列,按钮,增删改查调用】不用再写任何代码 -->
        <myTable ref="table" :auto="true" :query="tableQuery">
            <template slot="search">
                <el-form :inline="true" label-width="50px" style="height: 40px">
                    <el-form-item label="id">
                        <el-input v-model="filters.id" placeholder="" style="width:200px"></el-input>
                    </el-form-item>
                    <el-form-item label="名称">
                        <el-input v-model="filters.name" placeholder="" style="width:200px"></el-input>
                    </el-form-item>
                </el-form>
            </template>
        </myTable>
        <!-- 使用 auto="false" 需要自己定义列和增删改查函数  -->
        <myTable ref="table" :auto="false" :query="tableQuery">
            <el-table-column label="id-插槽"  prop="id"> </el-table-column>
            <el-table-column label="内容列-插槽" prop="name"></el-table-column>
            <el-table-column label="操作-插槽" >
                <template slot-scope="scope">
                    <el-button  size="small" type="button" @click="edit(scope)">编辑</el-button>
                    <el-button  size="small" type="button" @click="edit(scope)">编辑</el-button>
                    <el-button  size="small" type="button" @click="edit(scope)">编辑</el-button>
                    <el-button  size="small" type="button" @click="edit(scope)">编辑</el-button>
                    <el-button  size="small" type="button" @click="edit(scope)">编辑</el-button>
                    <el-button  size="small" type="button" @click="edit(scope)">编辑</el-button>
                    <el-button  size="small" type="button" @click="edit(scope)">编辑</el-button>

                    <el-button  size="small" type="danger" @click="del(scope.$index)">删除</el-button>
                </template>
            </el-table-column>
        </myTable>
        <addIndex ref="addIndex"></addIndex>
    </div>
</template>
<script>
 import addIndex from '@/views/components/add.vue'
export default ({
   name:'indexTest',
   components:{addIndex},
   data(){
    return {
       filters:{
        pageIndex:1,
        pageSize:5
       }
    }
   },
   methods:{
    //模拟请求返回
    tableQuery(){
        console.log('filters',this.filters)
          var p = new Promise((res,rej)=>{
            console.log(rej)
            setTimeout(() => {
                var value ={
                    columns:[{label:'序号',prop:'id'},{label:'名称',prop:'name'}],
                    buttons: {
                        add:{ url:'/controller/add',method:'post',data:{id:'',name:''},param:{}},
                        edit:{ url:'/controller/update',method:'post',data:{id:'',name:''},param:{}},
                        del:{url:'/controller/delete',method:'delete', data:{ },param:{id:''}}
                    },
                    data: [
                        {id:1,name:'测试1004' },
                        {id:2,name:'测试1009'},
                        // {id:3,name:'测试1009'},
                        // {id:4,name:'测试1009'},
                        // {id:5,name:'测试1009'},
                        // {id:6,name:'测试1009'},
                        // {id:7,name:'测试1009'},
                        // {id:8,name:'测试1009'},
                        // {id:9,name:'测试1009'},
                        // {id:10,name:'测试1009'},
                    ],
                    totalCount:200};

                    value.data =value.data.filter(x=>this.where(x))
                res(value)
            }, 1000);
        })
        return p
    },
    where(x){
        var a = this.filters.id ? x.id == this.filters.id : true
        var b = this.filters.name ? x.name.indexOf( this.filters.name)>-1 : true
        var r = a && b
        return r
    },
    edit(){},
    del(){}
   }
})
</script>
<style lang="scss" scoped>
table button{
    margin-top:10px;
}
</style>

add.vue

<template>

        <el-dialog :title="title"
        width="30%"
        :close-on-click-modal="false"
        :visible.sync="visible">
            <el-form  ref="form" :model="form" :rules="rules"  :label-width="'120px'">
              <el-form-item label="id" prop="id">
                <el-input v-model="form.id" placeholder=""></el-input>
              </el-form-item>
              <el-form-item label="名称" prop="name">
                <el-input v-model="form.name" placeholder=""></el-input>
              </el-form-item>
            </el-form>
            <div slot="footer" class="dialog-footer">
                <el-button @click="visible = false">取 消</el-button>
                <el-button type="primary" @click="add()">确 定</el-button>
            </div>
        </el-dialog>

</template>

<script>

export default ({
     name:'addTest',
     data(){
        return {
          title:'新增',
          visible:false,
          form:{},
          rules:{},
          save:null,
        }
     },
     methods:{
        show(save,form){
            this.visible=true
            this.save=save
            this.form =form?form:{}
        },
        showEdit(save,form){
          this.title='编辑'
          this.show(save,form)
        },
        add(){
          if(this.save!=null){
            this.save(this.form)
          }
          else{
            this.$message.success('ok2')
          }
          this.visible=false
        }
     }
})
</script>

到此这篇关于vue+elementUI,封装一个根据后端变化的动态table的文章就介绍到这了,更多相关vue elementUI封装table内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Vue+ElementUI table实现表格分页

    Vue+ElementUI table表格分页,供大家参考,具体内容如下 分页的两种方式.前端分页,后端分页.两种方式各有个的优缺点吧. 前端分页:后台只需将数据返回,不需要做过多处理,前端一次请求拿到所有数据后做分页处理.但数据量不能太大,因为前端是先一次性加载所有数据,然后在做分页处理.在数据量多的情况下,加载相对应的会变慢.所有在前端做分页时要先考虑一下后期的数据量. 后端分页:因为是后端分页,前端在每点击一次分页时,便向后台请求一次数据.其实就是避免前端一次性从数据库获取大量数据 一.在

  • vue+elementUI组件table实现前端分页功能

    前端分页和后端分页就是请求的差异,前端分页的话只请求一次,所以要在render table组件的时候控制下数据 :data="tableData.slice((currentPage-1)*pageSize,currentPage*pageSize)"   //不多解释 再就是设置分页器total等于table数据的长度 :total="tableData.length" 点击分页器的操作 methods: { handleSizeChange(val) { con

  • Vue ElementUI table实现表格斜线分隔线

    本文实例为大家分享了Vue ElementUI table给表格一个斜线分隔线的具体代码,供大家参考,具体内容如下 效果: 实现: 通过改css样式实现 1.去掉第一个单元格的下边框/2.第一列第一个单元格和第二个单元格的伪元素设置绝对定位,宽度设成1px,高度根据自己表格调整3.通过旋转两个单元格伪元素,并设置旋转起始点,使两个伪元素旋转到重合位置,达到斜线的效果 代码: 1.html <el-table     :data="tableData3"     style=&qu

  • VUE2.0+ElementUI2.0表格el-table实现表头扩展el-tooltip

    ElementUI2.0的表格的扩展: elementUI表格table elementUI文字提示Tooltip 如果要实现鼠标移到表头有注释或者弹框该怎么添加呢? <el-table empty-text="正在加载中..." :data="contentList" style="width: 100%" @sort-change="sort" class="pro-table-item" too

  • vue elementUI table 自定义表头和行合并的实例代码

    最近项目中做表格比较多,对element表格的使用,只需要传递进去数据,然后写死表头即可渲染. 但现实中应用中,如果写死表头,并且每个组件中写自己的表格,不仅浪费时间而且消耗性能.这个时候需要动态渲染表头. 而官方例子都是写死表头,那么为了满足项目需求,只能自己来研究一下. 1.自定义表头 代码如下,其实就是分了两部分,表格主数据是在TableData对象中,表头的数据保存在headerDatas,headerDatas.label其实就是表头的值,如果表头是"序号",那么header

  • vue elementUI table表格数据 滚动懒加载的实现方法

    在项目中遇到了一个性能问题 vue+elementUI table表格展示数据,当数据很多的时候,不能一页显示完,同时一次请求数据量太大,会增加网页渲染的时间,影响体验, 这个时候常常有两种方法处理, 1.分页,如下 2.如果我不想分页,又想在一页显示全部数据呢?这个时候其实就可以用数据懒加载了 如下一开始表格只显示31行数据 当将滚动条拉到低的时候,就会再加载31条数据,如果剩下的数据不足31,那就加载剩下的 根据项目需求,这需要一页可以看到全部数据,所以我选择了第二中方式 那么第二种方式要怎

  • vue+elementui实现点击table中的单元格触发事件--弹框

    elementui中提供了点击行处理事件 查看位置: elementui的table事件 elementui的table中怎样点击某个单元格触发事件? 可以先看一下官网中table的自定义列模板代码 <template> <el-table :data="tableData" border style="width: 100%"> <el-table-column label="日期" width="180

  • vue+elementUI封装一个根据后端变化的动态table(完整代码)

    实现了自动生成和插槽两个方式,主要把 el-table 和el-pagination封装在一起 效果图: 使用组件,启用自动生成 :auto="true" 自动生成-编辑 (包括请求已经实现了)新增和删除也是一样 ps:如有额外的按钮可以用插槽实现 查询的时候,只需要多返回下面数据,就可以自动生成列,和对应操作按钮 目录 table.vue <template> <div> <el-row v-if="auto"> <el-

  • 解决vue+elementui项目打包后样式变化问题

    博主刚刚解决了index.html空白问题,刚打开项目页面又发现了样式出现了大问题,样式与开发版本有很大不同,有些样式没有生效.利用搜索引擎, 找到了问题所在以及解决办法: main.js中的引入顺序决定了打包后css的顺序,组件内的样式没有生效可能是被第三方组件样式覆盖了,所以把第三方组件放在前面引入,router放在后面引入,就可以实现组件样式在第三方样式之后渲染. 代码如下: main.js // The Vue build version to load with the `import

  • Vue+ElementUI 封装简易PaginationSelect组件的详细步骤

    在实际开发工作中,经常会碰到当select下拉数据过需要做分页的情况这里简单介绍封装的一个Pagination-Select组件几个步骤封装的比较简易,可以根据自己的项目进行改动 /components/Pagination-Select/index.vue <template> <div id="PaginationSelect"> <el-select v-model="value" :placeholder="selec

  • vue3与elementui封装一个便捷Loading

    目录 前言 实际使用 代码实现 前言 因为后台管理,总要写很多loading状态的变量,然后控制开启和关闭..我个人很讨厌写这种重复的代码..所以为了少写点这种变量,所以突发奇想封装一个,目前感觉还是挺好用的,没出啥bug...在表格中也能运用自如..喜欢的话,可以复制到你自己的项目拿去用,记得点个赞噢 实际使用 代码实现 import { reactive } from 'vue' import { ElMessageBox, ElMessage } from 'element-plus' i

  • Vue实现封装一个切片上传组件

    目录 组件效果 使用文档 封装过程 1. 文件切片 2. 构造切片请求参数 3. 控制分片请求的并发 完整代码 待完善 组件效果 单文件切片上传 多文件切片上传 组件使用案例 <template> <div id="app"> <div class="upload-wrap"> <UploadSlice :action="uploadInfoSlice.actionChunk" :headers=&quo

  • element-ui封装一个Table模板组件的示例

    大家在做后台管理系统的时候,写的最多的可能就是表格页面了,一般分三部分:搜索功能区.表格内容区和分页器区.一般这些功能都是使用第三方组件库实现,比如说element-ui,或者vuetify.这两个组件库都各有各的优点,但就table组件来说,我还是比较喜欢vuetify的实现,不用手写一个个column,只要传入headers的配置数组就行,甚至分页器都内置在了table组件里,用起来十分方便.有兴趣可以看看:vuetify data table. 上面是一个经典的用element-ui开发的

  • javascript原生封装一个淡入淡出效果的函数测试实例代码

    说到js的渐变显示与消失,多数朋友会想到JQuery里面的fadeIn().fadeOut()或fadeToggle().但如果仅仅是为了引入这样的一个效果,而去调用了庞大JQuery库?或者说我通过用原生js实现一些函数来提高自己~ 所以,我简单的研究了一下纯js代码写淡入淡出的效果. 如果出现错误,请在评论中指出,我也好自己纠正自己的错误 (一)FadeIn淡入函数 淡入淡出的效果,其实就是一个setInterval(),加上循环的DOM操作,通过改变element对象节点的透明度,即可实现

  • jQuery实现响应鼠标背景变化的动态菜单效果代码

    本文实例讲述了jQuery实现响应鼠标背景变化的动态菜单效果代码.分享给大家供大家参考.具体如下: 这是一款jQuery响应鼠标背景变化的动态菜单,菜单的背景在鼠标放上后有所变化,这款菜单的实现主要是使用了图片,修改菜单的时候要修改图片,有些麻烦,不过效果不错,引入的jquery插件是1.7版本,高版本jQuery未测试,应该也可以啦. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/jquery-mouse-cha-bg-pic-menu-co

  • Flutter 封装一个 Banner 轮播图效果的实例代码

    实际业务开发中,首页一般都会存在一个轮播图. 在 Flutter 中,如何开发一个轮播? 了解需求 首先,我们在开发一个功能的时候要了解这个功能的需求,那一个轮播需要有什么功能? 1. 可以自定义高度和一些属性 2. 展示图片 3. 自动翻页播放 4. 点击事件 5. 指示器 6. 人为拖动的时候关闭自动播放 其中「人为拖动的时候关闭自动播放」是比较难的,我们后续会说,那先一个一个功能来实现. 自定义高度和一些属性 这里主要是做一些前期的工作,如果我们的 Banner 要开源让别人来使用,那我们

  • vue tree封装一个可选的树组件方式

    目录 组件实现的基本功能 先看效果图 组件实现的基本功能 1,根据后端返回的数据格式,传入组件动态的渲染出当前角色有哪些权限(新建,修改) 2,适配有2级和只有一级多选的数据 3,有全选(√) ,全不选 ,部分已选(-)的3装状态,每一级都支持(用的iview2次封装) 4,改变之后返回当前选中的所有权限的id,用于提交 5,手风琴效果,小屏适配 先看效果图 有部分权限没打开 打开 小屏 权限数据结构,select_status=1表示选中 默认添加没有权限的初始数据结构 有些数据只有一级子菜单

随机推荐