<h:selectOneMenu ...> <f:selectItems ... /> <f:ajax listener="#{bean.listener}" /> </h:selectOneMenu>
和
<h:selectOneMenu ... valueChangeListener="#{bean.listener}"> <f:selectItems ... /> </h:selectOneMenu>
<h:selectOneMenu value="#{bean.value}" valueChangeListener="#{bean.changeListener}"> <f:selectItems ... /> <f:ajax /> </h:selectOneMenu>
当使用< f:ajax listener>而不是valueChangeListener,它将默认在HTML DOM更改事件期间已执行。在UICommand组件和表示复选框或单选按钮的输入组件的内部,它将默认在HTML DOM点击事件期间执行。
<h:selectOneMenu value="#{bean.value}"> <f:selectItems ... /> <f:ajax listener="#{bean.ajaxListener}" /> </h:selectOneMenu>
另一个主要区别是在PROCESS_VALIDATIONS阶段结束时调用valueChangeListener方法。此时,提交的值尚未在模型中更新。所以你不能通过访问绑定到输入组件的值的bean属性来获得它。你需要通过ValueChangeEvent#getNewValue()获取它。旧的值也是可用的ValueChangeEvent#getOldValue()。
public void changeListener(ValueChangeEvent event) { Object oldValue = event.getOldValue(); Object newValue = event.getNewValue(); // ... }
< f:ajax listener>方法在INVOKE_APPLICATION阶段被调用。此时,已提交的值已在模型中更新。你可以通过直接访问绑定到输入组件的值的bean属性来获得它。
private Object value; // +getter+setter. public void ajaxListener(AjaxBehaviorEvent event) { System.out.println(value); // Look,(new) value is already set. }
另外,如果您需要基于提交的值更新另一个属性,那么当您使用valueChangeListener时,它会失败,因为更新的属性可以在随后的UPDATE_MODEL_VALUES阶段期间被提交的值覆盖。这就是为什么你在旧的JSF 1.x应用程序/教程/资源中看到一个valueChangeListener在这样的结构中与immediate =“true”和FacesContext#renderResponse()结合使用来防止这种情况发生。毕竟,使用valueChangeListener来执行业务操作实际上总是一个黑客/解决方法。
总结:仅当需要截取实际值更改本身时,才使用valueChangeListener。也就是说你实际上对旧的和新的值感兴趣(例如,记录他们)。
public void changeListener(ValueChangeEvent event) { changeLogger.log(event.getOldValue(),event.getNewValue()); }
使用< f:ajax listener>只有当您需要对新更改的值执行业务操作时。也就是说您实际上只对新值感兴趣(例如填充第二个下拉列表)。
public void ajaxListener(AjaxBehaviorEvent event) { selectItemsOfSecondDropdown = populateItBasedOn(selectedValueOfFirstDropdown); }
如果您在执行业务操作时实际上对旧值感兴趣,则回退到valueChangeListener,但将其排队到INVOKE_APPLICATION阶段。
public void changeListener(ValueChangeEvent event) { if (event.getPhaseId() != PhaseId.INVOKE_APPLICATION) { event.setPhaseId(PhaseId.INVOKE_APPLICATION); event.queue(); return; } Object oldValue = event.getOldValue(); Object newValue = event.getNewValue(); System.out.println(newValue.equals(value)); // true // ... }