Vue+Element组件封装
使用element经常需要用表格展示数据,对表格内容进行分页以及搜索都是比较常见的需求;于是想到了对element进行二次封装;主要涉及的组件有el-table、el-dropdown(控制每页展示条目数)、el-pagination(table分页)、el-input(搜索框)。效果预览创建项目//注: el-table-ly 是项目名字vue init webpack-simple el-ta
·
使用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>
更多推荐
已为社区贡献1条内容
所有评论(0)