1、背景
兴安盟网站制作公司哪家好,找创新互联公司!从网页设计、网站建设、微信开发、APP开发、响应式网站设计等网站项目制作,到程序开发,运营维护。创新互联公司2013年开创至今到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选创新互联公司。
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选择项的数据数组。
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 {
right: 0;
top: 1px;
}
.el-input__inner {
padding: 0 25px;
}
&.el-input--mini {
width: 175px;
}
&.el-input--medium {
width: 195px;
}
}
// input padding
.el-input__inner {
padding: 0 5px;
}总结
以上所述是小编给大家介绍的vue elementui 实现搜索栏公共组件封装,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对创新互联网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!