如何用Elemental2/GWT高效映射DataTables的可变参数API?
在GWT中用Elemental2简洁集成DataTables的方案
问题背景
我希望在GWT中通过Elemental2使用原生JavaScript库DataTables。该库的初始化API示例如下:
$('#example').DataTable({ paging: false, ordering: false, info: false, columnDefs: [ { targets: [2,3], orderable: false }, { targets: [0], width : "150px" }, { targets: [3], width : "90px"} ] });
该库的初始化参数具有高度可变性、数量繁多且为可选参数。我最初尝试通过@JsType定义Java类来映射API,虽然可行但实现过程十分繁琐:
@JsType(isNative = true,name = "DataTable", namespace = JsPackage.GLOBAL) public class DataTable { public DataTable(String selector, FeatureOptions options){} public native Api clear(); public native Api draw(); // and so on... } @JsType(isNative = true, name = "Object", namespace = JsPackage.GLOBAL) public class FeatureOptions { public String scrollY; public boolean scrollCollapse; public boolean paging; public boolean searching; // and so on... }
尤其是面对columnDefs这类复杂类型时,需要定义大量额外类,因此我转而使用JSNI实现:
public native void drawTable(String tableID)/*-{ var table = $wnd.$('#'+tableID).DataTable({ searching : false, "columnDefs": [ { targets: [2,3], orderable: false }, { targets: [0], "width" : "150px" }, { targets: [3], "width" : "90px"} ] }); }-*/;
我想请教是否存在一种简洁高效的纯Elemental2实现方式,比如使用Map填充所需参数并以JSON字符串形式传递?
解决方案
方案1:用Elemental2的JsObject和数组直接构建配置
Elemental2提供的JsObject对应JS普通对象、JsArray对应JS数组,可直接构建DataTables需要的配置结构,无需定义大量Java类:
import elemental2.dom.DomGlobal; import elemental2.core.JsObject; import elemental2.core.JsArray; public void initDataTable(String tableId) { // 构建columnDefs数组 JsArray<JsObject> columnDefs = JsArray.of(); // 第一个列配置 JsObject def1 = JsObject.create(); def1.set("targets", JsArray.of(2, 3)); def1.set("orderable", false); columnDefs.push(def1); // 第二个列配置 JsObject def2 = JsObject.create(); def2.set("targets", JsArray.of(0)); def2.set("width", "150px"); columnDefs.push(def2); // 第三个列配置 JsObject def3 = JsObject.create(); def3.set("targets", JsArray.of(3)); def3.set("width", "90px"); columnDefs.push(def3); // 构建主配置对象 JsObject config = JsObject.create(); config.set("paging", false); config.set("ordering", false); config.set("info", false); config.set("searching", false); config.set("columnDefs", columnDefs); // 初始化DataTables DomGlobal.window.$("#" + tableId).DataTable(config); }
这种方式完全基于Elemental2 API,不需要JSNI,且只需按需构建所需参数,不用覆盖所有配置项。
方案2:用JsPropertyMap简化属性设置
Elemental2的JsPropertyMap是更灵活的键值容器,语法更紧凑:
import elemental2.dom.DomGlobal; import elemental2.core.JsPropertyMap; import elemental2.core.JsArray; public void initDataTable(String tableId) { // 构建columnDefs数组 JsArray<JsPropertyMap<Object>> columnDefs = JsArray.of(); columnDefs.push(JsPropertyMap.of( "targets", JsArray.of(2, 3), "orderable", false )); columnDefs.push(JsPropertyMap.of( "targets", JsArray.of(0), "width", "150px" )); columnDefs.push(JsPropertyMap.of( "targets", JsArray.of(3), "width", "90px" )); // 构建主配置 JsPropertyMap<Object> config = JsPropertyMap.of( "paging", false, "ordering", false, "info", false, "searching", false, "columnDefs", columnDefs ); DomGlobal.window.$("#" + tableId).DataTable(config); }
JsPropertyMap.of()可一次性初始化多个属性,代码更简洁,适合快速构建配置对象。
额外说明
如果需要调用DataTables实例方法(如clear()、draw()),可将初始化返回的对象存为JsObject类型,再通过call()方法调用:
JsObject dataTable = DomGlobal.window.$("#" + tableId).DataTable(config); // 调用clear方法 dataTable.call("clear"); // 调用draw方法 dataTable.call("draw");
内容的提问来源于stack exchange,提问作者Sandro
相关产品推荐
相关产品推荐

