layui中实现动态的cols表头字段
layui中实现动态的cols表头字段需求确定修改前修改后parseData方法done函数解决方案先创建工具类处理逻辑需求确定最近再搞一个需求时,需要在layui中实现表头字段的动态更新,无奈转战前端阵营来一波官方文档先,个人感觉还是挺简单易懂的https://www.layui.com/doc/再来个在线演示网站https://www.layui.com/demo/table/height.h
需求确定
最近再搞一个需求时,需要在layui中实现表头字段的动态更新,无奈转战前端阵营
来一波官方文档先,个人感觉还是挺简单易懂的
https://www.layui.com/doc/
再来个在线演示网站
https://www.layui.com/demo/table/height.html
修改前
layui.render中默认调用的接口的返回值是集合类型,所以根据一一匹配的原则可以快速的生成表头和表数据。但如果我们的表头是动态生成的,那就有些麻烦了,这里要涉及到表头的数据以及表格的数据。
原来是这样的
layui.use('table', function() {
var table = layui.table;
table.render({
elem: '#tableList'
, url: '/web/aliyunOSSMetric/query?day=' + day + '&company=' + company
, toolbar: true
, height: 'full-330'
, cols: [
[
{field: 'bucket', width: 420, title: 'bucket' }
,{ title:'操作', toolbar: '#tableListAction', width:120}
, {field: 'companyName', width: 150, title: '厂商', sort: true}
, {field: 'value', width: 200, title: '流量(TB)', sort: true}
, {field: 'percent', width: 200, title: '比例', sort: true}
]
]
});
});
修改后
parseData方法
在table中,我们可以关注到一个异步回调函数parseData
,能够对回调的数据进行一些处理,例如将数据格式化。本来我也打算用这个来渲染cols的,但是这个是在数据返回之后的,cols已经在该方法之前便生效了,所以只能另辟蹊径
done函数
同理,done函数也能做一些事情,但是cols也已经在该函数前便已生效
解决方案
在render方法之前,先请求接口获取数据,并可以处理成想要的格式,在render中直接对cols直接赋值就可以了
layui.use('table', function() {
let table = layui.table;
let cols = []
let col = []
$.ajax({
type: 'POST',
url: '/web/aliyunOSSMetric/getCols?day=' + end + '&buckets=' + '&company=' + company,
dataType: "JSON",
sync: false,
contentType: "application/json",
success: function (res) {
col.push({field: 'bucket', width: 420, title: 'bucket',merge: true});
col.push({title:'操作', toolbar: '#tableListAction', width:120});
col.push({field: 'companyName', width: 150, title: '厂商', sort: true, rowspan: 1});
$.each(res.data, function (index, obj) {
col.push({field: obj, width: 200, title: obj, sort: true, rowspan: 1});
});
col.push({field: 'percent', width: 200, title: '比例', sort: true, rowspan: 1});
cols.push(col);
table.render({
elem: '#tableList'
,
url: '/web/aliyunOSSMetric/query?day=' + end + '&company=' + company
,
toolbar: true
,
height: 'full-330'
,
cols: cols
});
}
});
});
那么我们会想到,cols是不固定的,那么后端返回的集合类型的每个元素的属性数量也是不固定的
针对后端的返回类型,我们可以抽象为Object集合
针对每个Object,我们可以通过动态的改变业务对象的属性数量,再将业务对象转成json对象,再向上转型成Object对象
具体如下:
先创建工具类
import com.google.common.collect.Maps;
import net.sf.cglib.beans.BeanGenerator;
import net.sf.cglib.beans.BeanMap;
import org.apache.commons.beanutils.PropertyUtilsBean;
import java.beans.PropertyDescriptor;
import java.util.Map;
/**
* @author junfeng.lin
* @date 2021/9/2
*/
public class ReflectUtil {
public static Object getTarget(Object dest, Map<String, Object> addProperties) {
PropertyUtilsBean propertyUtilsBean =new PropertyUtilsBean();
PropertyDescriptor[] descriptors = propertyUtilsBean.getPropertyDescriptors(dest);
Map<String, Class> propertyMap = Maps.newHashMap();
for(PropertyDescriptor d : descriptors) {
if(!"class".equalsIgnoreCase(d.getName())) {
propertyMap.put(d.getName(), d.getPropertyType());
}
}
// add extra properties
addProperties.forEach((k, v) -> propertyMap.put(k, v.getClass()));
// new dynamic bean
DynamicBean dynamicBean =new DynamicBean(dest.getClass(), propertyMap);
// add old value
propertyMap.forEach((k, v) -> {
try{
// filter extra properties
if(!addProperties.containsKey(k)) {
dynamicBean.setValue(k, propertyUtilsBean.getNestedProperty(dest, k));
}
}catch (Exception e) {
e.printStackTrace();
}
});
// add extra value
addProperties.forEach((k, v) -> {
try{
dynamicBean.setValue(k, v);
}catch (Exception e) {
e.printStackTrace();
}
});
Object target = dynamicBean.getTarget();
return target;
}
public static class DynamicBean {
/**
* 目标对象
*/
private Object target;
/**
* 属性集合
*/
private BeanMap beanMap;
public DynamicBean(Class superclass, Map<String, Class> propertyMap) {
this.target = generateBean(superclass, propertyMap);
this.beanMap = BeanMap.create(this.target);
}
/**
* bean 添加属性和值
*
* @param property
* @param value
*/
public void setValue(String property, Object value) {
beanMap.put(property, value);
}
/**
* 获取属性值
*
* @param property
* @return
*/
public Object getValue(String property) {
return beanMap.get(property);
}
/**
* 获取对象
*
* @return
*/
public Object getTarget() {
return this.target;
}
/**
* 根据属性生成对象
*
* @param superclass
* @param propertyMap
* @return
*/
private Object generateBean(Class superclass, Map<String, Class> propertyMap) {
BeanGenerator generator =new BeanGenerator();
if(null != superclass) {
generator.setSuperclass(superclass);
}
BeanGenerator.addProperties(generator, propertyMap);
return generator.create();
}
}
}
处理逻辑
service层进行处理
Map<String,Object> properties = Maps.newHashMap();
//动态添加属性,其中第一个参数是属性名,第二个参数是属性值
properties.put(ossMetric.getName(), entity.getValue());
ObjectMapper mapper = new ObjectMapper();
//先转成JSON对象
String json = mapper.writeValueAsString(ReflectUtil.getTarget(vo,properties)); //其中vo是具体的业务对象
//再将JSON对象转成实体类,由于不知道具体的属性值是怎么样的,所以向上转型用Object接收
Object ossMetricVo = JSONObject.parseObject(json, Object.class);
最后在controller中直接将Object数组返回给前端就可以了
controller中的伪代码
@RequestMapping("/aliyunOSSMetric/query")
public Map<String,Object> queryByDay(@RequestParam(name = "day") String day,
@RequestParam(name = "company") String company
) throws InvocationTargetException, JsonProcessingException {
Map<String,Object> res = new HashMap<>();
List<Object> data = service.query(day, company);
res.put("code", 0);
res.put("msg", "");
res.put("count", data .size());
res.put("data", data);
return res;
}
如此,前端就能根据cols中的属性名自动匹配到data中对象的属性名了,大功告成!
更多推荐
所有评论(0)