# 代码控制页面
通过Meper设计的页面,除了可以在页面中设定页面加载、数据源的绑定外,实施人员也可以通过代码控制页面。也就是说可以使用Meper单单做一个页面设计器,然后通过代码控制后端逻辑。这样可以完全将页面设计和后台控制逻辑分开。
例如:实施者可以在Meper中设定各个组件要显示的国际化,权限,表格(以及各个栏位的数据源定义),然后再代码中直接从数据库获取数据加载进页面即可。后续如果有调整页面的必要,比如直接增加一个Column显示额外信息 那么可以直接在页面中调整即可,不需要再调整代码。
系统中有两个入口类来完成这样的功能 BaseViewModel 和 BaseDialogViewModel,在实施者完成ViewModel的代码后,需要将该Java类定义的完整路径写入PageEditor中,如下图所示:
# BaseViewModel
一切页面的基类
public abstract class BaseViewModel {
private WidgetRunningModel runningModel = WidgetRunningModel.PREVIEW;
/**
* 页面初始化后,自动会被调用。用户可以在此方法中进行数据的初始化
*/
public abstract void init();
public void showAsDialog(String popupName, String popupRevision, String eventName, EventListener eventListener) {
LumosPopupDialog lumosPopupDialog =
new LumosPopupDialog(popupName, Strings.isNullOrEmpty(popupRevision) ? "1" : popupRevision, runningModel);
lumosPopupDialog.registerEventListener(eventName, eventListener);
lumosPopupDialog.show();
}
public LumosPopupDialog createDialog(String popupName, String popupRevision) {
return new LumosPopupDialog(popupName, Strings.isNullOrEmpty(popupRevision) ? "1" : popupRevision,
new ActionContext(), runningModel);
}
public WidgetRunningModel getRunningModel() {
return runningModel;
}
public void setRunningModel(WidgetRunningModel runningModel) {
this.runningModel = runningModel;
}
}
如上代码示例,该类提供的一个核心方法为 createDialog, 也就是说,如果页面有需要显示弹出框的需要,可以直接调用该方法创建一个弹出框页面并直接调用弹出框的getViewModel方法,进行数据的设定,然后显示。
# BaseDialogViewModel
一切弹出框的基类
public abstract class BaseDialogViewModel extends BaseViewModel {
private LumosPopupDialog dialog;
public void updateDialogResult(ConfirmResult.Result result, Object value) {
getDialog().ifPresent(item -> {
item.setRunningResult(new ConfirmResult(result, value));
});
}
public void updateDialogResult(ConfirmResult.Result result) {
getDialog().ifPresent(item -> {
item.setRunningResult(new ConfirmResult(result));
});
}
public void updateDialogResult(Object value) {
getDialog().ifPresent(item -> {
item.setRunningResult(new ConfirmResult(value));
});
}
public void closeDialog() {
getDialog().ifPresent(LumosPopupDialog::close);
}
public Optional<LumosPopupDialog> getDialog() {
return Optional.of(dialog);
}
public void setDialog(LumosPopupDialog dialog) {
this.dialog = dialog;
}
public abstract void onDialogOpen();
}
通过DialogViewModel,可以很方便的获取Dialog,反之通过Dialog,可以很方便的获取属于该Dialog的一个ViewModelClass。
通过该类,可以很方便的对Dialog进行操作,如获取,打开,关闭一个窗体等,
# Widget
一个将页面设计和后台代码组件建立关系的关键注解,在Meper解析完成后,会根据该注解为ViewModel类中的控件进行赋值。
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Widget {
/**
* widget 的id定义
*
* @return
*/
String value();
}
样例:
public class UserViewModel extends BaseViewModel {
@Widget(value = "ID_BUTTON_ADD")
private Button btnAdd;
@Widget(value = "ID_GRID_grid")
private PaginationObjectListGrid grid;
@Override
public void init() {
}
}
如上的代码中,在UserViewModel初始化完成后,btnAdd和grid变量中,会被Meper放入值,用户直接使用即可。
# 初始化
所有的页面在被Meper解析后,加载顺序为:
- 解析并生成页面,优先加载页面中的各种设定,如基本属性设定、数据源设定、事件的定义等
- 根据PageEditor(页面设计定义)找到对应的ViewModel,并为其生成实例
- 根据@Widget注解,将页面中的控件注入ViewModel,至此,页面与ViewModel建立关系,可以在ViewModel中很好的控制页面元素