最近遇到一个需求:需要实现前端列表页根据后端配置实现自动化生成。期初这个需求是没有头绪的因为就目前接触到的页面来看,用到的列表出了长的比较像意外其实没有完全一样的,基本上没有两个完全没有自定义操作且产品给的原型还是一样的列表。但是遇到需求吗没法的时候就得上。
一般列表页 基本都会含有以下几个结构
一.搜索区(分为条件区域 + 按钮区域)
1)条件区域一般常用的有 输入框,选择框,单选按钮组,多选按钮组,还有联级选择器等、因为要做的是配置所以这里必须尽可能的把每一个条件可能出现的情况考虑到。但是这样的话整个模块就会变得很臃肿。所以第一个版本打算先固定样式和页面风格,同时忽略掉正则这些验证实现简单的版本 大体条件区域的配置可以是这样的
{
"type": "需要使用的条件类型 比如input或者selet等",
"placeholder": "提示语",
"label": "表单的label",
"param": "接口接收此参数的字段名称"
},
这里给一个对象params 接口需要的参数都会挂载到这个对象上 有些条件的选择是需要从接口拿回来数据的 那么拿回来的数据会统一挂载到selectionConfig对象上 相应的selectionConfig的key值最好和查询接口需要的key统一 这样有利于直接取值也比较有规律,要不写接口的人换一下就还得协商一次比较麻烦。当然这里我们也可以写一个转换器来转换拿回来的数据
{
"接口需要的关键值key":"条件对应的关键值key",
"id":"ids",
},
选择的条件大多是从接口拿回来的数据那么配置里面肯定还有一个参数是回去条件的接口地址。这里为了方便处理我们默认一个页面只有一个获取条件的接口,不然接口多了要处理同步异步的话就比较麻烦 我们给这个信息取名为getSelectUrl 而他的转化器配置则为getSelectUrlConfig,
而那些需要实时搜索的下拉我们可以单独进行封装,然后给这个组件定义一个type remote
组件结构
组件js
那么条件配置也基本成型
{
"type": "remote",
"placeholder": "id",
"label": "",
"param": "id",
//用来转换查询接口和最终参数的配置
"transform":{
"key":"admin_id",
"value":"cn_name",
"secondValue":"admin_name"
}
"url":"动态获取的url"
},
处理当前列表是否默认查询
searchConfig.immediatelySearch = true;//true,默认进入页面就查询,false默认不查询
到这里基本需要配置也完成了
list 完整 代码
{{it.value}}
{{$t("message.button.search")}}
{{$t("message.button.reset")}}
{{$t("message.button.more")}}
{{$t("message.closeAccount_button.export")}}{{searchConfig.exportUrl}}
{{ scope.row[item.key] }}
{{ scope.row[item.key] }}
配置模拟返回json文件
{
"code": 200,
"data": {
"tableConfig": {
"addConfigUrl":"",
"addSaveUrl":"",
"editSaveUrl":"",
"detailUrl":"",
"editConfigUrl":"",
"operations": "labelListHandel",
"isNeedPage":true,
"border":false,
"tableHeaderArr": [{
"value": "在线邮寄方式",
"key": "shipping_service",
"width":""
},
{
"value": "仓库",
"key": "warehouse_name",
"components": "",
"width":"150"
},
{
"value": "状态",
"key": "is_use",
"components":"changeStatus",
"width":"200"
},
{
"value": "更新人",
"key": "oa_create_user_name",
"width":"150"
},
{
"value": "更新时间",
"key": "edit_date",
"width":"300"
}
]
},
"searchConfig": {
"isShowMoreSearch":false,
"immediatelySearch":true,
"exportUrl": "",
"searchUrl":"/shipment/shippingList",
"getSelectUrl":"/shipment/getSearchFields",
"getSelectConfig":{
"shipping_method_id":"shipping_method_list",
"warehouse_id":"warehouse_list"
},
"getSelectParams":{
"shipping_method_list":1,
"warehouse_list":1,
"country_list":1,
"tag_list":1,
"tag_type_list":1,
"country_type_list":1
},
"default":{
"status":"1"
},
"operations": "openLabelSearch",
"operationsWidth":"300px",
"model": "params",
"formCom": [{
"type": "select",
"placeholder": "在线邮寄方式",
"label": "",
"param": "shipping_method_id"
},
{
"type": "select",
"placeholder": "仓库",
"label": "",
"param": "warehouse_id",
"data": []
},
{
"type": "select",
"placeholder": "是否启用",
"label": "",
"param": "status",
"data": [{
"key": "1",
"value": "是"
},
{
"key": "0",
"value": "否"
}
]
},
{
"type": "employees",
"placeholder": "更新人",
"label": "",
"param": "admin_id"
}
],
"formComMore":[
]
}
}
}
默认的我们会把所有的组件挂载到这个对象上
以下是这个组件的示例 components.js
/**
*
* @desc 列表操作部分使用import 引入 搜索操作使用 require 动态引入
*/
const listButton = r => require(['@/components/pages/hotManSystem/listButton'], r)
// 新增标签
const openLabelSearch = r => require(['@/components/pages/OADelivery/openLabelSearch'], r)
// 新增快递方式
const addMethodDelivery = r => require(['@/components/pages/OADelivery/addMethodDelivery'], r)
//列表内的组件一定要使用import的方式引入 如果动态引入第一次查询的时候将不会渲染组件
// 外部链接
import outLink from "@/components/common/link/outLink";
// 标签操作
import labelListHandel from "@/components/pages/OADelivery/labelListHandel";
//
export const components = {
// 公共的的组件
outLink: outLink,
"openLabelSearch": openLabelSearch,
// 查看标签
"labelListHandel": labelListHandel,
//快递方式搜索新增
"addMethodDelivery": addMethodDelivery,
//列表操作组件
"methodDeliveryOpptions": methodDeliveryOpptions,
}
在所有的自定义组件上 我们将会挂载列表页可能的数据到组件上 方便在调用到的子组件内使用 并定义回调方法
混合查询的通用方法searchMixin.js
/*
* 列表搜索的 mixin
*/
import {
resCode
} from '@/config/consts'
import {
getExportFormComItem
} from '@/config/tools'
export const listSearch = {
data () {
return {
// 加载中
loading: false,
// 页面的列表数据
listData: []
}
},
methods: {
/*
* 处理页面序号的变化
*/
indexMethod (index) {
if (this.page === 1 || this.page === 0) return index + 1
return ((this.page - 1) * this.page_size) + index + 1
},
/*
* 搜索函数
*/
search () {
let self = this
let params = self.getParams()
if (!params) return false
self.loading = true
let config = {
url:params.url,
loading:params.loading || "loading",
contentType:params.contentType || "form",
param:params.data || {}
}
// 若为单选则更新
self.$restful.sendMyData(config,self, (res)=> {
if(res.code === 200)
self.listData = res.data.rows || []
if (res.data.total || res.data.total ===0) {self.page_info.total = Number(res.data.total)}
})
// self.elForm 为导出组件的引用,如果有用到,需要在组件的mounted中定义如: self.elForm = self.$refs['elForm']
// 调用导出插件的刷新函数
// getExportFormComItem 的参数为【页面搜索的条件】,为 {} 类型
self.elForm && self.elForm.refresh(getExportFormComItem(params.data))
},
/*
* 改变页面显示的条数
*/
handleSizeChange (page_size) {
this.page_size = page_size
this.search()
},
/*
* 改变页码
*/
handleCurrentChange (page) {
this.page = page
this.search()
},
/*
* 获取参数,这个方法必须在组件中去覆盖,不然应该提示错误
* 可以理解为后台的抽象函数
*/
getParams () {
let self = this
self.$message.error('请在组件的methods中定义获取参数的方法 [ getParams ]')
return false
},
}
}
合并混合查询方法
mixin.js
import { listSearch } from './searchMixin.js'
export const listSearchMixin = {
...listSearch
}
以上就是简单的自动化配置列表的全部代码了 后面的可以根据具体的业务做条件和其他业务模块的扩展