侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

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

前端  /  管理员 发布于 5年前   1033

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选择项的数据数组。

 

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 实现搜索栏公共组件封装,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对站的支持!

如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

您可能感兴趣的文章:

  • elementUi vue el-radio 监听选中变化的实例代码
  • vue+elementUI 复杂表单的验证、数据提交方案问题
  • vue elementUI使用tabs与导航栏联动
  • vue elementui el-form rules动态验证的实例代码详解
  • vue elementUI table 自定义表头和行合并的实例代码
  • vue elementUI table表格数据 滚动懒加载的实现方法
  • VUE2.0+ElementUI2.0表格el-table循环动态列渲染的写法详解
  • VUE2.0 ElementUI2.0表格el-table自适应高度的实现方法


  • 上一条:
    DIV背景半透明文字不半透明的样式
    下一条:
    阿望教你用vue写扫雷小游戏
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 使用 Alpine.js 排序插件对元素进行排序(0个评论)
    • 在js中使用jszip + file-saver实现批量下载OSS文件功能示例(0个评论)
    • 在vue中实现父页面按钮显示子组件中的el-dialog效果(0个评论)
    • 使用mock-server实现模拟接口对接流程步骤(0个评论)
    • vue项目打包程序实现把项目打包成一个exe可执行程序(0个评论)
    • 近期文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • Laravel 11.15版本发布 - Eloquent Builder中添加的泛型(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-03
    • 2018-04
    • 2018-05
    • 2018-06
    • 2018-09
    • 2018-11
    • 2018-12
    • 2019-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2021-04
    • 2021-05
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客