logo资料库

vue elementui 实现搜索栏公共组件封装的实例代码.pdf

第1页 / 共9页
第2页 / 共9页
第3页 / 共9页
第4页 / 共9页
第5页 / 共9页
第6页 / 共9页
第7页 / 共9页
第8页 / 共9页
资料共9页,剩余部分请下载后查看
vue elementui 实现搜索栏公共组件封装的实例代码 实现搜索栏公共组件封装的实例代码 1、背景、背景 vue后台管理系统,会有很多表格页面,表格上方会有一些搜索选项,表格直接使用el-table即可,而搜索栏区域每次写起来都很繁琐,而且多人开发情况下每个人写的样式都不相 同,布局样式无法统一。 所以要考虑对搜索栏做一个封装,统一配置引用,提升开发维护效率和界面统一。 完成后的效果大概就是长这样: 2、分析、分析 项目使用的是elementui框架,搜索栏这种表单提交,首先要使用el-form组件来封装,而复杂点就是表单项可能有很多种,例如input输入框、select选择框、日期时间选择框、日期时 间范围选择框、cascader级联选择框等,每一项的字段名prop、名称label、绑定的属性方法都不尽相同。所以不能通过普通的绑定个别属性的方式来处理,而slot插槽的方式也无法 简化,最终决定通过传递一个配置项数组的形式来解析生成相应的结构。 3、实现、实现 目前实现的方式由两部分组成,一部分是form表单组件,接受父组件传递的配置项数组,一部分是封装一些常用的表单项组件,通过v-if来控制,form表单组件里引入该表单项组件, 循环遍历,根据传递的表单项类型来匹配显示具体的表单项。 form表单组件(searchForm.vue)示例代码: formItem表单项组件(formItem.vue)示例代码: 4、关键点 、关键点 由于elementui表单组件本身有很多配置属性,不可能把所有的属性和方法都写死封装,要想无缝支持,需要用到vue的v-bind和v-on特性,vue的v-bind和v-on支持赋值为对象类 型,vue会自动遍历对象里的属性依次绑定,v2.4.0+支持。 5、参数配置项解释 、参数配置项解释 (1)示例: [{ label: '用户名', // label文字 prop: 'username', // 字段名 element: 'el-input', // 指定elementui组件 initValue: '阿黄', // 字段初始值 placeholder: '请输入用户名', // elementui组件属性
rules: [{ required: true, message: '必填项', trigger: 'blur' }], // elementui组件属性 events: { // elementui组件方法 input (val) { console.log(val) }, } }] label 用于绑定给el-form-item上的label,表单项标题 prop 用于绑定给el-form-item上的prop,字段名,必填 element 指定elementui表单项的组件名,必填 initValue 表单项的初始值,可选 events 对象,对象里加方法,js原生方法或者elementui表单项组件支持的方法都可以加进去,通过v-on遍历绑定 … 其他elementui表单项组件支持的属性或者html原生属性都可以添加,常用的例如rules表单校验、placeholder提示,通过v-bind遍历绑定 (2)参数传递解析的流程: 首先,searchForm.vue组件里通过props接收参数: formOptions: { type: Array, required: true, default () { return [] } }, created组件里处理初始值: // 添加初始值 addInitValue () { const obj = {} this.formOptions.forEach(v => { if (v.initValue !== undefined) { obj[v.prop] = v.initValue } }) this.formData = obj } 一部分配置项绑定在el-form-item上,一部分传递给formItem表单项组件再绑定: formItem.vue表单项组件里props接受传参: itemOptions: { type: Object, default () { return {} } } computed里处理接收的参数itemOptions,生成要绑定的所有属性对象bindProps: // 绑定属性 bindProps () { let obj = { ...this.itemOptions } // 移除已使用的或不相关的冗余属性 delete obj.label delete obj.prop delete obj.element delete obj.initValue delete obj.rules delete obj.events if (obj.element === 'el-select') { delete obj.options } return obj }, computed里生成要绑定的所有方法对象bindEvents: // 绑定方法 bindEvents () { return this.itemOptions.events || {} }, 最后dom里使用这些数据绑定: (3)特殊情况的处理 由于elementui的el-select里是通过el-option遍历实现的,而遍历数组options按elementui官方不是绑定在el-select上的,所以针对el-select的配置项再加一个options里属性,即select 选择项的数据数组。
v-on="bindEvents" size="mini" clearable > elementui的日期时间选择器分了很多种,根据业务需要分别处理一下,我这里是根据type划分成了三种分开处理,最常用的是datetimerange日期时间范围选择器,作为默认项,还 有一种monthrange,其余的都划为一种。(具体处理见文章末尾的完整代码) 6、按钮组 、按钮组 按钮其实就那么几个,没必要做太多的封装,根据业务有哪些按钮就封装进去,目前我这里就封装了三个按钮。 通过props接受一个字符串标识按钮组: // 提交按钮项,多个用逗号分隔(query搜索, export导出, reset重置) btnItems: { type: String, default () { return 'search' } } 7、使用方式示例 、使用方式示例 dom: vue data里: formOptions: [ { label: '意见内容', prop: 'content', element: 'el-input' }, { label: '类型', prop: 'type', element: 'el-select', options: [ { label: '给点意见', value: '1' }, { label: '售后问题', value: '2' } ] }, { label: '状态', prop: 'status', element: 'el-select', options: getFeedbackStatus() }, { label: '提交时间', prop: 'timeRange', element: 'el-date-picker' } ], vue methods里: // 获取搜索表单提交的数据 onSearch (val) { console.log(val) } 8、完整代码 、完整代码 (1)searchForm.vue /** * Created by hanxueqiang on 200107 * * 搜索栏公共组件 */ (2)formItem.vue /** * Created by hanxueqiang on 200107 * * 表单匹配项 */ (3)依赖引入的一些函数方法 tools.js /** * 创建唯一的字符串 * @return {string} ojgdvbvaua40 */ function createUniqueString () { const timestamp = +new Date() + '' const randomNum = parseInt((1 + Math.random()) * 65536) + '' return (+(randomNum + timestamp)).toString(32) } // elementui日期时间范围 快捷选项 const pickerOptionsRange = { shortcuts: [ { text: '今天', onClick (picker) { const end = new Date() const start = new Date(new Date().toDateString()) start.setTime(start.getTime()) picker.$emit('pick', [start, end]) } }, { text: '最近一周', onClick (picker) { const end = new Date() const start = new Date() start.setTime(end.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]) } } ] } // elementui月份范围 快捷选项 const pickerOptionsRangeMonth = { shortcuts: [ { text: '今年至今', onClick (picker) { const end = new Date() const start = new Date(new Date().getFullYear(), 0) picker.$emit('pick', [start, end]) } }, { text: '最近半年', onClick (picker) { const end = new Date() const start = new Date() start.setMonth(start.getMonth() - 6) picker.$emit('pick', [start, end]) } }, { text: '最近一年', onClick (picker) { const end = new Date() const start = new Date() start.setMonth(start.getMonth() - 12) picker.$emit('pick', [start, end]) } } ] } (4)一些elmentui全局样式的修改 // el-input-number (controls-position="right") .el-input-number.is-controls-right { .el-input-number__decrease { display: none; } .el-input-number__increase { display: none; top: 2px; // fix style bug } &:hover { .el-input-number__decrease { display: inline-block; } .el-input-number__increase { display: inline-block; } } .el-input__inner { text-align: left; padding-left: 5px; padding-right: 40px; } } // el-date-picker datetimerange .el-date-editor.el-date-editor--datetimerange { .el-range-separator { width: 24px; color: #999; padding: 0; } .el-range__icon { margin-left: 0; } &.el-input__inner { vertical-align: middle; padding: 3px 5px; } &.el-range-editor--medium { width: 380px; .el-range-separator { line-height: 30px; } } &.el-range-editor--mini { width: 330px; .el-range-separator { line-height: 22px; } } } // el-date-picker not datetimerange .el-date-editor { .el-input__prefix { left: 0; top: 1px; } .el-input__suffix {
分享到:
收藏