Vue+Element组件封装

2023-10-26

使用element经常需要用表格展示数据,对表格内容进行分页以及搜索都是比较常见的需求;于是想到了对element进行二次封装;主要涉及的组件有el-table、el-dropdown(控制每页展示条目数)、el-pagination(table分页)、el-input(搜索框)。
效果预览
在这里插入图片描述

创建项目

//注: el-table-ly 是项目名字
vue init webpack-simple el-table-ly

在这里插入图片描述
删繁就简:src目录下删除所有文件,新建lyTable.vue和main.js
在这里插入图片描述
二次封装的组件如何进行数据和事件的绑定呢?
使用组件通信来进行数据和事件绑定 示例如下:

数据绑定

// lyTable.vue   子组件

    <el-table :data="data_table">
    	<slot></slot>   //此处使用slot插槽为了方便下面父组件传递 <el-table-column>
    </el-table>

    props:{
        data:{}
    },
//使用封装的组件库 父组件 
<ly-table :data="table">
	<el-table-column prop="name" label="name"></el-table-column>
	<el-table-column prop="value" label="value"></el-table-column>
<ly-table>

    data() {
        return {
	    table:['name':'ly','value':'xixi'] 
        }
    },

事件绑定:

//lyTable.vue 子组件

	<el-table :data="data_table" @row-click="handleRowClick">
		<slot></slot>
	</el-table>
    
    	methods: {
        	handleRowClick(row, column, event){
            		this.$emit('row-click',row, column, event);
        	}
    	}
//使用封装的组件库 父组件 

      	<ly-table :data="table" @row-click="rowClick"></ly-table>
	
	data(){
	    return{
		table:['name':'ly','value','xixi']
	    }
	},
	methods:{
		rowClick(){
		    //row-click点击事件代码
		}
	}

进行封装后的 lyTable.vue 代码如下

<template>
  <div style="margin-bottom: 20px;margin: 10px 20px 10px 20px;">
    <div> 
        <div style="float:left;padding-top:10px">
        <label style="font-weight:bold;">Show</label>  
        <el-dropdown trigger="click" @command="handleCommand">
            <span class="el-dropdown-link">
                {{data_pageSize}}<i class="el-icon-arrow-down el-icon--right"></i>
            </span>
            <el-dropdown-menu slot="dropdown">
                <el-dropdown-item command="10">10</el-dropdown-item>
                <el-dropdown-item command="25">25</el-dropdown-item>
                <el-dropdown-item command="50">50</el-dropdown-item>
                <el-dropdown-item command="100">100</el-dropdown-item>
            </el-dropdown-menu>
        </el-dropdown>     
        <label style="font-weight:bold;">entries</label>  
        </div>
        <div class="search-Box" style="float:right;width:250px;height:40px;padding-right:10px;">
                <el-label style="float:left;font-weight:bold;padding-top:10px">Search:</el-label>
                <el-input style="display:inline;float:right;width:180px" prefix-icon="el-icon-search" placeholder="请输入搜索内容"
                 icon="search" class="search" v-model="data_search"></el-input>
        </div>
    </div>
<el-table :data="(data_filter_table=tables).slice((data_currentPage-1)*data_pageSize,data_currentPage*data_pageSize)" :stripe="stripe" :border="border" :height="height" 
              :max-height="max_height" :size="size" :show-header="show_header" :highlight-current-row="highlight_current_row" :current-row-key="current_row_key" 
              :row-class-name="row_class_name" :row-style="row_style" :cell-class-name="cell_class_name" :cell-style="cell_style" :row-key="row_key" 
              :show-summary="show_summary" @select="handleSelect" @select-all="handleSelectAll" @selection-change="handleSelectionChange"
              @cell-mouse-enter="handleCellMouseEnter" @cell-mouse-leave="handleCellMouseLeave" @cell-click="handleCellClick" @row-click="handleRowClick"
              @header-click="handleHeaderClick" ref="ref_table">
        <slot></slot>
    </el-table>
    <div style="padding-top:10px;vertical-align:middle">
        Showing {{data_show_first}} to {{data_show_end}} of {{data_filter_table_length}} entries
        <span v-if="data_filter_table_length!=data_total">(filtered from {{data_total}} total entries)</span>
        <el-pagination style="float:right" layout="prev, pager, next" :page-size="data_pageSize" :total="data_filter_table.length"
         background @current-change="handleCurrentPage" :current-page="data_currentPage"></el-pagination>
    </div>
  </div>
</template>

<script>
  export default {
    props:{
        data:{},
        stripe:{default:true},
        border:{default:true},
        height:{default:null},
        max_height:{default:null},
        size:{default:null},
        show_header:{default:true},
        highlight_current_row:{default:false},
        current_row_key:{default:null},
        row_class_name:{default:null},
        row_style:{default:null},
        cell_class_name:{default:null},
        cell_style:{default:null},
        row_key:{default:null},
        show_summary:{default:false},
        ref_table:{default:null}
    },
    data() {
        return {
            data_total:100,//默认数据总数
            data_pageSize:10,//每页的数据条数
            data_currentPage:1,//默认开始页面
            data_search: '',  //搜索内容
            data_filter_table:[], //搜索过滤后的数据table
        }
    },
    watch:{
        tables(val){
            this.data_filter_table = val;
            this.data_currentPage = 1;
        }
    },
    computed: {
        // 模糊搜索 过滤父组件 :data传递给子组件的table内容
        tables:function(){
            var data_search=this.data_search;
            if(data_search){
                return  this.data.filter(function(dataNews){
                    return Object.keys(dataNews).some(function(key){
                        return String(dataNews[key]).toLowerCase().indexOf(data_search) > -1
                    })
                })
            }else{
                this.data_total = this.data.length;
            }
            return this.data;
        },
        data_pageSize(){
            return this.data_pageSize;
        },
        data_search: {
            get () {
                return this.data_search;
            },
            set (val) {
                this.data_search = val;
            }      
        },
        data_total(){
            return this.data_total;
        },
        data_filter_table_length(){
            return this.data_filter_table.length;            
        },
        data_show_first(){
            return ((this.data_currentPage-1)*(this.data_pageSize)+1)>this.data_filter_table.length?0:((this.data_currentPage-1)*(this.data_pageSize)+1);         
        },
        data_show_end(){
            return (this.data_currentPage*(this.data_pageSize))>this.data_filter_table.length?this.data_filter_table.length:(this.data_currentPage*(this.data_pageSize));
        },
        data_currentPage(){
            return this.data_currentPage;
        },
    },
    methods: {
        handleCommand(val){
            this.data_pageSize = val;
            this.data_currentPage = 1;
        },
        handleCurrentPage(val){
            this.data_currentPage = val;
        },
        //el-table 对应事件
        handleSelect(selection, row){
            this.$emit('select',selection, row);
        },
        handleSelectAll(selection){
            this.$emit('select-all',selection);
        },
        handleSelectionChange(selection){
            this.$emit('selection-change',selection);
        },
        handleCellMouseEnter(row, column, cell, event){
            this.$emit('cell-mouse-enter',row, column, cell, event);
        },
        handleCellMouseLeave(row, column, cell, event){
            this.$emit('cell-mouse-leave',row, column, cell, event);
        },
        handleCellClick(row, column, cell, event){
            this.$emit('cell-click',row, column, cell, event);
        },
        handleRowClick(row, column, event){
            this.$emit('row-click',row, column, event);
        },
        handleHeaderClick(column, event){
            this.$emit('header-click',column, event);
        },
        clearSelection(){
            this.$refs.ref_table.clearSelection();
        },
        toggleRowSelection(row, selected){
            this.$refs.ref_table.toggleRowSelection(row, selected);
        },
        toggleAllSelection(){
            this.$refs.ref_table.toggleAllSelection();
        },
        setCurrentRow(row){
            this.$refs.ref_table.setCurrentRow(row);
        }
    }
  };
</script>

修改webpack配置文件

//webpack.config.js

const path = require('path')
const webpack = require('webpack')
function resolve(dir) {
  return path.join(__dirname, '..', dir)
}

module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'vue-ly-table.min.js',  //打包输出的名字
    library: 'lyTable',   //指定使用时的模块名
    libraryTarget: 'umd',
    umdNamedDefine: true
  },
  module: {
    rules: [
      {
        test: /\.(js|vue)$/,
        loader: 'eslint-loader',
        enforce: 'pre',
        include: [resolve('src'), resolve('test')],
        options: {
          formatter: require('eslint-friendly-formatter')
        }
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        loader: 'file-loader',
        options: {
          name: '[name].[ext]?[hash]'
        }
      }
    ]
  },
  resolve: {
    alias: {
      vue$: 'vue/dist/vue.esm.js'
    }
  },
  externals: {
    vue: {
      root: 'Vue',
      commonjs: 'vue',
      commonjs2: 'vue',
      amd: 'vue'
    }
  },
  devServer: {
    historyApiFallback: true,
    noInfo: true
  },
  performance: {
    hints: false
  },
  devtool: '#source-map'
}

if (process.env.NODE_ENV === 'production') {
  module.exports.devtool = '#source-map'
  module.exports.plugins = (module.exports.plugins || []).concat([
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"'
      }
    }),
    new webpack.optimize.UglifyJsPlugin({
      sourceMap: false,
      compress: {
        warnings: false
      }
    }),
    new webpack.LoaderOptionsPlugin({
      minimize: true
    })
  ])
}

修改package.json

// 修改 package.json
{
  "name": "el-table-ly",
  "version": "1.0.0",
  "main": "dist/vue-ly-table.min.js", //对应webpack.config.js 输出的filename
  "description": "Encapsulate the element twice, combine el-table with pagination, search and the number of rows displayed on the current page.",
  "author": "linyuan <870327274@qq.com>",
  "private": false,  //需要发布npm包即设为false
  "scripts": {
   "build": "webpack --config webpack.config.js --progress --hide-modules"
  },
  ......
 }


编写main.js

import lyTable from './lyTable.vue';
//导出模块 以便项目引用
export default lyTable;
//注册组件
if (typeof window !== 'undefined' && window.Vue) {
  window.Vue.component('ly-table', lyTable);
}

项目打包

//打包  会在 dist目录下生成vue-ly-table.min.j
npm run build 

发布npm包

1.npm官网注册账号
2.回到项目目录下  
npm login
3.npm publish 
发布成功后就可以去npm搜索发布的包了 注意每次发布版本号需要不一样

组件库使用方法

注意:本组件依赖如下包,如果没有请安装
vue
   npm install vue
elementUI
   npm i element-ui -S
   
npm i el-table-ly


//xxx.vue

import lyTable from 'el-table-ly'

components: { lyTable }

<ly-table :data="dataTable"></ly-table>

使用示例:

//简单示例
    <ly-table :data="dataTable">
        <el-table-column type="selection"></el-table-column>
        <el-table-column prop="host" label="主机" sortable></el-table-column>
        <el-table-column prop="name" label="名称" sortable></el-table-column>
        <el-table-column prop="expression" label="表达式" sortable></el-table-column>
        <el-table-column prop="status" label="状态" sortable></el-table-column>
        <el-table-column label="删除">
            <el-button type="danger" size="mini" icon="el-icon-delete" circle></el-button>
        </el-table-column>
    </ly-table>

import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI);
import lyTable from 'el-table-ly'

export default {
    name: 'mgr_manage',
    components: { lyTable },
    data() {
        return {
            dataTable:[{"host":"h25","name":"xxx25h28","expression":"111","status":"ok"},
                        {"host":"h28","name":"xxx28","expression":"2222xxx","status":"warning"},
                        {"host":"h25","name":"yyy25","expression":"2222xxx","status":"warning"},
                        {"host":"h25","name":"xxx25","expression":"111xxx","status":"ok"},
                        {"host":"h28","name":"xxx28","expression":"2222xxx","status":"warning"},
                        {"host":"h25","name":"yyy25","expression":"2222xxx","status":"warning"},
                        {"host":"h25","name":"xxx25","expression":"111xxx","status":"ok"},
                        {"host":"h28","name":"xxx28","expression":"2222xxx","status":"warning"},
                        {"host":"h25","name":"yyy25","expression":"2222xxx","status":"warning"},
                        {"host":"h25","name":"xxx25","expression":"111xxx","status":"ok"},
                        {"host":"h28","name":"xxx28","expression":"2222xxx","status":"warning"},
                        {"host":"h25","name":"yyy25","expression":"2222xxx","status":"warning"}]
        }
    }
}

注:没有将el-table所有属性和事件全部封装,只封装了一部分。

ly-table支持的属性

    data,
    stripe,
    border
    height,
    max_height,
    size,
    show_header,
    highlight_current_row,
    current_row_key,
    row_class_name,
    row_style,
    cell_class_name,
    cell_style,
    row_key,
    show_summary
    
基本和el-table使用方法一致,只是需要使用v-bind   
比如 <ly-table :data="dataTable" :highlight_current_row="true"></ly-table>
    @select 
    @select-all 
    @selection-change
    @cell-mouse-enter
    @cell-mouse-leave 
    @cell-click 
    @row-click 
    @header-click
    
使用和el-table一致        
比如 <ly-table @row-click="handleRowClick"></ly-table>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Vue+Element组件封装 的相关文章

随机推荐

  • MATLAB实现BO-CNN-GRU贝叶斯优化卷积门控循环单元多输入分类预测

    作者简介 热爱科研的Matlab仿真开发者 修心和技术同步精进 matlab项目合作可私信 个人主页 Matlab科研工作室 个人信条 格物致知 更多Matlab仿真内容点击 智能优化算法 神经网络预测 雷达通信 无线传感器 电力系统 信号
  • Linux常识型试题

    http www linuxdiyf com viewarticle php id 202718 一 填空题 1 链接分为 和 2 安装Linux系统对硬盘分区时 必须有两种分区类型 和 3 内核分为进程管理系统 I O管理系统和 等四个子
  • anki插件【Enhance main window】配置

    book symbol cap value null color empty red color empty descendant green color zero false columns absolute true color be3
  • TCP/IP三次握手

    序列号seq 占4个字节 用来标记数据段的顺序 TCP把连接中发送的所有数据字节都编上一个序号 第一个字节的编号由本地随机产生 给字节编上序号后 就给每一个报文段指派一个序号 序列号seq就是这个报文段中的第一个字节的数据编号 确认号ack
  • 三种方法使用FFmpeg截取视频片断

    如何以 3 种简单的方式使用 FFmpeg 剪切视频 提取 修剪 2020 年 10 月 12 日 Krishna Rao Vijayanagar FFmpeg 在本教程中 我们将了解如何使用 FFmpeg 以 3 种不同的方式剪切 修剪
  • 渗透测试工程师的一些面试题2(同样适合一些刚入门的小白看哦~~~!)

    一 信息收集 服务器的相关信息 真实ip 系统类型 版本 开放端口 WAF等 网站指纹识别 包括 cms cdn 证书等 dns记录 whois信息 姓名 备案 邮箱 电话反查 邮箱丢社工库 社工准备等 子域名收集 旁站 C段等 googl
  • Qt5开发从入门到精通——第一篇概述

    欢迎小伙伴的点评 相互学习 互关必回 全天在线 博主 本着开源的精神交流Qt开发的经验 将持续更新续章 为社区贡献博主自身的开源精神 文章目录 一 什么是 Qt 1 1 Qt 的发展 1 2 Qt 版本说明 1 3 Qt5开发环境简介 二
  • 约瑟夫问题(Java环形列表实现)

    package linkedList public class Joseph public static void main String args CircleLinkList cir new CircleLinkList cir add
  • 陆续收集 UE4 常用的宏的用法

    UPROPERTY EditAnywhere 任何地方 UPROPERTY EditDefaultsOnly 只有在类的编辑界面 UPROPERTY EditInstanceOnly 只有在拖拽到场景下类的编辑界面 UClass meta
  • Linux终端界面的字体颜色设置

    目录 说明 PS1 颜色语法 保存设置 说明 在网上找了好多资料都不是很详细 要不就是语法有错误 所以弄了好久才整明白了 写下来方便后面的人学习 本人Linux虚拟机版本为CentOS 6 5其他的版本的可能又细微区别哈 PS1 PS1是L
  • C++ Primer 学习笔记 第八章 IO库

    C 不直接处理输入输出 而是通过一族定义在标准库中的类型来处理IO 这些类型支持从设备读取数据 向设备写入数据的IO操作 设备可以是文件 控制台窗口等 IO库定义了读写内置类型值的操作 此外 一些类 如string 通常也会定义类似的IO操
  • 自动化测试基础

    1 自动化测试定义 自动化测试就是实用软件来控制测试案例的执行 对测试进行自动化的过程就是写一段代码来代替人工测试 可以分为两种方式 代码驱动测试 通过大量的输入参数和对应的返回结果 来验证类 模块 或者库文件的公共接口是否正确 普遍使用测
  • xss-labs前五关 详细

    其它xss文章 以xss labs举例反射型xss注入的方式及基本思路 xss实验并对注入点 注入语句及危害知识总结 other article to be continue 第一关 lt 1 gt 解法 直接在url栏的name 后输入
  • 钻石基础知识介绍

    钻石参数 4C 最重要的钻石的重量也就是克拉数 克拉数有一个克拉溢价 也就是30分 50分 1克拉 1 5克拉 2克拉 2 5克拉 达到这些阈值的时候 价格会成倍增长 因此对于自己戴的买一些低于阈值的钻石更划算 但是如果想要保值还是尽量买高
  • ARPA x 京东数科:隐私计算如何赋能未来金融数据共享

    数据是现代商业与个人的核心价值与重要资产 数据正在重新塑造人类生活的方方面面 IDC Research统计2019年大数据和分析市场的销售收入约为1870亿美元 跨机构 跨行业的数据融合 联合分析和建模的需求日趋增加 但由于数据本身可复制
  • 快手出海求生

    配图来自Canva可画 随着八月接近尾声 众多上市公司的中期成绩单纷纷出炉 这其中就有视频社区B站 游戏直播斗鱼等内容平台的财报 不过 从其披露的财报中可以看出 如今内容平台的发展都不容乐观 而作为 短视频双雄之一 的快手近期交出的答卷中
  • WebSphere之wasprofile.sh使用

    概要文件 profile 6 0版本以后才有profile 目的是将用户数据和was本身的文件分开 这样可以定义多个profile 每个profile相当于一个用户 相当于提供了多用户的支持 profile的命令说明 新建 wasprofi
  • vue-echarts饼图/柱状图点击事件

    在实际的项目开发中 我们通常会用到Echarts来对数据进行展示 有时候需要用到Echarts的点击事件 增加系统的交互性 一般是点击Echarts图像的具体项来跳转路由并携带参数 当然也可以根据具体需求来做其他的业务逻辑 下面就Echar
  • UGUI—事件,iTween插件

    预计两三天内 做2048游戏和一款自己编写的方块小游戏 期待一下喽 每日一句 游戏制作是声色张扬下我欲盖弥彰的温柔理想 目录 UGUI事件 事件注册 通过编辑器绑定方法 AddListener 实现接口 自定义框架 iTween动画库 自动
  • Vue+Element组件封装

    使用element经常需要用表格展示数据 对表格内容进行分页以及搜索都是比较常见的需求 于是想到了对element进行二次封装 主要涉及的组件有el table el dropdown 控制每页展示条目数 el pagination tab