搜索组件_高级前端架构师炼成记27之搜索组件的封装使用

一、开发背景

  2年前做了一个基于element-ui的layout组件发布到npm package上去,广受大家的欢迎,下载量每周颇升。这个组件的好处在于开发者不用写太多html代码和逻辑,只要通过配置json的方式就能马上生成后台,包括菜单栏和导航面包屑等一键生成,还能根据不同的需求做定制化后台界面,就像拼积木一样,让用户只专注于内容核心代码的开发。现在还没做大范围的推广,如果我觉得它做得足够好,我一定会放到npm上推荐给各位读者使用哈。当初为了解答网友的疑问,我还专门建立了该组件的官网。logo看起来有没有很熟悉?哈哈哈,它其实就是element-ui的logo进行改造的,意义就是告诉使用者,这是element-ui功能的组合加强版。

907db5410e18d930035ed586b546b390.png

  为了迎合公司的OKR,我提出了对表单表格组件的封装。为什么我会有这个想法?其实这个组件我很早就想做了,只是以前做的是基于UI层面的,近期我接手了公司的一个项目叫童画,每天做的事情感觉就是复制粘贴,修改部分不同的功能和字段名称。组件的意义在于可以在遇到同一类设计场景时,可以复用,从而减少设计的时间和形成产品的统一性。传统的搜索表单不就是这样吗?上面是表单搜索字段,中间是搜索结果的表格,下面是搜索结果的分页。把表单和表格组合起来的好处在于很多搜索字段都是基于表格组件的某些字段,那我根据search字段进行筛选不就可以了么,很久之前,我们总是在吐槽产品经理总是喜欢截图现有功能,然后做字段修改,搞成原型扔给前端。如果前端也能像他这样简单,那该多好呀,类似这样的想法油然而生。刚开始我只是为了方便我的工作,没想到领导却重视了起来,想把这个组件推广给公司其他十几个前端同事使用,于是乎,我便认真开搞了起来。有理论还不行,得有场景实践,刚好公司的项目童画有很多场景,我根据它里面的场景,做了很多功能的封装和兼容。

  写到这里,有人会说了,这不就是CRUD组件吗?有这想法的话,说明你还太年轻和小看这个组件的功能了。传统的CRUD组件灵活性不是很高,这个组件的好处是配置即可用,不用考虑其他搜索,翻页,清空等各种逻辑,让组件达到高度复用,封装了场景的插槽类型,但为了防止翻车,我还是预留了变态需求的插槽。字段的使用更多采用elementUI的命名方式,让使用者减少学习成本。这样做的好处是什么呢?首先,前端再也不用写页面了,其次,对于比较规矩的搜索表单页面,完全可以通过请求接口的形式交给后端来配置呈现页面即可,根本没有前端什么事了,前端的工作可以解放出来做更复杂的功能开发。

二、部分原理

  1. 搜索字段通过search=true进行筛选;

  2. 分页通过请求的total总数进行分页;

  3. Vue.prototype.$query接入请求。

三、组件文档

    为了使用方便,我把它做成了组件并放到了公司的私服上,接下来的工作就是写文档啦,以下是部分文档的编写,因为时间问题,没来得及好好检查,各位看官将就看一下就行啦。

3.1 版本升级

  • [0.0.0] 项目初始化

  • [0.0.1] 文档编写

  • [0.0.2] 属性字段的修改

3.2 如何使用

确保安装好elementUI

npm install element-ui --save

3.3 安装

    先切回到公司内部npm源

nrm use xxx

    Windows系统安装

npm install search-table --save

    Mac系统安装

sudo npm install search-table --save

3.4 更新

npm install search-table@latest

3.5 组件列表

   search-table 布局组件

3.6 引用

main.js

import Vue from "vue"import ElementUI from 'element-ui'import 'element-ui/lib/theme-chalk/index.css'Vue.use(ElementUI)import SearchTable from "search-table"Vue.use(SearchTable)import axios from 'axios'const http = axios.create({  baseURL: '/'})http.interceptors.request.use(config => {  let userInfo = getCookie(xxx)  if (userInfo) {      userInfo = JSON.parse(decodeURIComponent(userInfo))      config.headers['Access-Token'] = userInfo.accessToken  }  return config})Vue.prototype.$query = http

[page].vue

...  "options" ref=  ...import options from './options'export default {...data () {  return {    ...options  }},methods: {  showDialog ({id}) {    this.$confirm('确认已联系过本用户吗?', '提示', {      confirmButtonText: '确定',      cancelButtonText: '取消',      type: 'warning'    }).then(async () => {      let res = await auditionStatus({id, status: 2})      this.notifyMX(res, '处理成功')      this.$refs.SearchTable.getTableData()    }).catch(() => {})  },  handleOperation (val, ...arg) {    switch (val) {      case 'handle':        this.showDialog(...arg)        break      default:        break    }  }}...}

3.7 使用示例 

【与[page].vue同级建立options.js文件】

export default {options: {  request: {    api: '/student/web/student/enroll/list',    method: 'GET',    paramMap: {      index: 'pageIndex',      limit: 'pageSize'    },    resultMapping: {      total: 'total',      data: 'pageData'    }  },  size: '',  // medium/mini/small, 默认medium  labelWidth: 90,  submitBtn: true, // 搜索按钮,默认true,非必填  submitText: '查询', // 搜索按钮的文字,默认查询,非必填  clearBtn: true, // 清除按钮,默认true  clearSize: 'mini', // medium/mini/small, 默认medium  clearText: '清除', // 清除按钮的文字,默认清除,非必填  column: [    {       slotType: 'selection'    },    {      prop: 'keyword',      label: '学员/家长',      search: true,      hide: true    },    {      prop: 'studentName',      label: '学员'    },    {      prop: 'telephone',      label: '家长手机号',      width: 130    },    {      prop: 'type',      label: '报名类型',      width: 90,      search: true,      type: 'select',      slot: true,      slotType: 'text',      slotArray: [{        label: '新报',        value: 1      },      {        label: '续报',        value: 2      }],      dicData: [{        label: '新报',        value: 1      },      {        label: '续报',        value: 2      }]    },    {      prop: 'courseFee',      label: '缴费金额',      slot: true,      slotType: 'regEx',      regEx: '¥{{courseFee/100}}'    },    {      prop: 'payType',      label: '支付方式',      search: true,      type: 'select',      width: 100,      dicData: [        {          label: '微信',          value: '微信'        },        {          label: '支付宝',          value: '支付宝'        },        {          label: '银行卡转账',          value: '银行卡转账'        },        {          label: '其它',          value: '其它'        }      ]    },    {      prop: 'courseCount',      label: '报名课时'    },    {      prop: 'followTeacher',      label: '跟进人'    },    {      prop: 'createTime',      label: '报名时间',      param: 'beginTime,endTime',      format: 'yyyy 年 MM 月 dd 日',      valueFormat: 'timestamp',      search: true,      width: 160,      type: 'daterange'    },    {      prop: 'auditor',      label: '报名老师',      search: true,      param: 'teacherId', // 修正请求参数名      type: 'select',      dicData: [],      dicUrl: '/org/web/org/user/list/teacher',      dicMap: {        label: 'userName',        value: 'id'      }    },    {      prop: 'status',      label: '报名状态',      slot: true,      slotType: 'tag',      width: 110,      slotArray: [{        type: 'warning',        label: '待审核',        value: 1      },      {        type: 'danger',        label: '审核不通过',        value: 3      },      {        type: 'success',        label: '审核通过',        value: 2      }],      dicUrl: ''    },    {      prop: 'operation',      label: '操作',      width: 80,      slot: true,      slotType: 'operation',      slotArray: [        {          label: '去审核',          value: 'handle',          filter: ({status}) => {            return status === 1          }        }      ]    }  ]}}

3.8 参数说明

Variables

参数说明类型可选值默认值
options组件配置属性,详情见下面options属性Object--


Events

事件名说明参数
on-search点击搜索后触发该事件,非必填-
on-page切换页面时触发该事件,非必填-
on-selection当选择项发生变化时会触发该事件,非必填-
on-select当搜索选择列表发生变化时会触发该事件,非必填-
on-operation当"操作"(包括'switch-change')发生变化时会触发该事件属性slotArray[{value}]

Methods [this.$refs.SearchTable]

方法名说明参数
setOptionData获取select选项数据接口后塞入的字段{result: res.data,label: 'name',value: 'id',target: 'courseName'}
getTableData重新请求该页面事件-

 

Options Attributes

参数说明类型可选值/例子默认值
request.url请求地址,必填项String/student/web/audition/list-
request.method请求方法,可不填Stringget/postget
request.paramMap.index请求映射index参数StringpageIndexpageIndex
request.paramMap.size请求映射size参数StringpageSizepageSize
request.resultMap.total请求映射total参数Stringtotaltotal
request.resultMap.data请求映射data参数StringpageDatapageData
size表单组件的大小Stringmedium/mini/smallmini
labelWidthlabel的宽度String-70
submitBtn是否显示搜索按钮Booleantrue/falsetrue
submitText搜索文本String-查询
clearBtn是否显示清空按钮Booleantrue/falsetrue
clearText清空文本String-清除
column表格配置属性,详情见下面Column属性Array-[ ]

Column Attributes

参数说明类型可选值默认值
prop字段参数String--
param当请求参数与字段不同时,可用该参数修正,多参用逗号隔开,非必填String'beginTime,endTime'/'teacherId'-
widthth 宽度,非必填String--
formattype=daterange时,'yyyy 年 MM 月 dd 日'Stringyyyy 年 MM 月 dd 日-
valueFormattype=daterange时,值的显示格式Stringtimestamptimestamp
label字段名称String--
hide隐藏字段,仅搜索表单显示,表格不显示的字段Boolean--
search是否是搜索字段Booleantrue/falsefalse
searchType搜索表单组件类型, 当search=true时才有效Stringselect/input/daterangeinput
dicDataselect选项的值Array[{label:'',value:''}][]
dicUrlselect选项的请求地址String--
dicMap.labellabel字段映射String--
dicMap.valuevalue字段映射String--
slottable字段是否使用插槽Booleantrue/falsefalse
slotTypetable插槽类型Stringselection/tag/image/text/button-
slotArray表格插槽显示字段的各种值,对象中,可加filter字段方法过滤条件显示Array[Object][{type:'success',label:'文本',value:'',filter:()=>{}}]-
searchRight表格头部(搜索)右侧内容插槽显示字段的各种值Array[Object][{type:'',label:'',value:'',filter:()=>{}}]-

Scoped Slot

默认插槽, 用以处理复杂字段
参数说明
列的名称列自定义列的内容,参数为{row,label,dic,$index}
searchRight表格头部(搜索)右侧内容

 ba8b4c6d58546fcd0ec0323500e5d76e.png

四、最后感谢

        最后,感谢同事世丞在字段命名上给了很多建议,同时也感谢领导给了很多刁难的意见,让这个组件的功能越发强大,也让开发者使用更方便,达到配置即可使用的地步。当然了,组件还需要更多场景的训练才能真正实现各种功能的兼容。后期我希望可以尽快放到layout官网上,供大家使用。

五、关于作者

    一个会美工与后端PHP/nodejs的全栈工程师

    更多学习内容欢迎关注

    今日头条号/微信公众号 :程序员周先生

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值