本来想直接用vue3来实现这个组件的,但是公司原先是在vue2+element的基础上封装的这个页面规格的组件。先把这个更新后下篇更新vue3+element-plus实现常规页面组件。
个人博客地址:https://web-miji.com/article?id=19
源码地址: GitHub - fengligao/vue-template-page-2: 页面模版组件
下面我们先来看下目录结构:
常用的组件我把它放到components文件下面。通过全局注册达到全局便捷使用无需多处引用。components/index.js代码:
import Vue from 'vue'
import TemplatePage from './template-page/index'
// 大家可以根据自己项目特性或者喜欢的特殊标识添加前缀
Vue.component('miji-template-page', TemplatePage)
main.js的代码如下:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import 'element-ui/lib/theme-chalk/index.css'
import './plugins/element.js'
import './components/index'
因为使用element我们也要把element引入引来。
实现常规页面的组件封装我们先来梳理下页面中分别都有什么功能?
分页展示,条件查询,新增,编辑,删除。常规的操作就这几个,那么我们就有了实现思路。
我们先来来看下页面效果:
我们先来实现页面的基本框架。
首先我们在components下创建一个template-page的文件夹,在它下面创建index.js这是我们页面的主代码文件。不是用.vue template模版的方式是因为jsx通过函数条件来动态生成想要的dom会节省大量的html代码。让我们代码的可读性更高。逻辑也更清楚,而不是使用大量的if else来判断页面展示逻辑。
render() {
return (
<div class="page">
<div class="page-form">
条件筛选区域
</div>
<div class="page-option">
操作区域
</div>
<div class="page-container">
内容区域
</div>
</div>
)
}
以上就是大致框架,分为三部分:条件查询区,其他操作区,内容展示区。
我们首先来看看条件筛选区域的实现:
首先这里根据外部传入的表单数组来渲染对应的筛选控件。我们默认定制好常用的几种:input、select、checkbox、radio、datePicker。其他的后续可以自行扩展。然后表格根据传入的列数组动态渲染。操作区域添加插槽代码。分页,数据请求等操作都通过动态配置来实现。
下面看看详细代码:
import './index.less'
const tableListJson = [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄',
age: 18,
status: 0
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄',
age: 19,
status: 1
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄',
age: 20,
status: 1
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄',
age: 21,
status: 0
}]
const pickerOptions = {
shortcuts: [{
text: '最近一周',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
picker.$emit('pick', [start, end]);
}
}, {
text: '最近一个月',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
picker.$emit('pick', [start, end]);
}
}, {
text: '最近三个月',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
picker.$emit('pick', [start, end]);
}
}]
}
export default {
props: {
// 筛选标准字段有以下几个:
// form[<Object>]
// type 控件类型 // input, select, date, radio, checkbox
// key 请求参数key
// label 控件名称
// value 控件值
// defaultValue: 默认值
// placeholder 控件提示
// disabled 是否禁用
// options 数据项
// getOptions 异步获取数据项
// props 自定义数据项key
// 时间日期控件会多以下几个字段
// dateType 时期控件类型 datetime/datetimerange/daterange
// format 日期显示格式
// valueFormat 选中值格式
// isPickerOptions 是否带快捷选项
form: {
type: Array,
default: () => []
},
// 表格配置
tableConfig: {
type: Object,
default: () => {
return {
title: '',
rowKey: 'id'
}
}
},
// 请求配置
requestConfig: {
type: Object,
required: true
},
// 请求方法
requestMethod: {
type: String,
default: () => 'Get'
},
// 请求前 参数处理的回调
beforeRequest: {
type: Function,
default: () => null
},
// 请求后 数据处理的回调
afterResponse: {
type: Function,
default: () => null
},
// 加载提示配置
loadingConfig: {
type: Object,
default: () => {
return {
text: '拼命加载中',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.8)'
}
}
},
// 表格列配置
// 单元格的配置列字段包含以下几种:
// column[Object]
// label 单元格名称
// prop 单元格数据展示key
// type 单元格类型 text map option
// slot 如果是插槽 单元格插槽名称
// map 单元格 枚举对象
// fixed