1.在自己的代码中创建包 com.jfinal.template.stat.ast;
2.创建类 For,具体代码如下:
package com.jfinal.template.stat.ast; import com.jfinal.template.Env; import com.jfinal.template.expr.ast.Expr; import com.jfinal.template.expr.ast.ForCtrl; import com.jfinal.template.expr.ast.Logic; import com.jfinal.template.io.Writer; import com.jfinal.template.stat.Ctrl; import com.jfinal.template.stat.Scope; import java.util.Iterator; public class For extends Stat { private ForCtrl forCtrl; private Stat stat; private Stat _else; public For(ForCtrl forCtrl, StatList statList, Stat _else) { this.forCtrl = forCtrl; this.stat = statList.getActualStat(); this._else = _else; } public void exec(Env env, Scope scope, Writer writer) { scope = new Scope(scope); // 将forCtrl往group中传递 scope.setLocal("forCtrl",this.forCtrl); if (this.forCtrl.isIterator()) { this.forIterator(env, scope, writer); } else { this.forLoop(env, scope, writer); } } private void forIterator(Env env, Scope scope, Writer writer) { Ctrl ctrl = scope.getCtrl(); Object outer = scope.get("for"); ctrl.setLocalAssignment(); ForIteratorStatus forIteratorStatus = new ForIteratorStatus(outer, this.forCtrl.getExpr().eval(scope), this.location); ctrl.setWisdomAssignment(); scope.setLocal("for", forIteratorStatus); Iterator<?> it = forIteratorStatus.getIterator(); String itemName = this.forCtrl.getId(); while(it.hasNext()) { // 将it往group中传递 scope.setLocal("forIterator",it); scope.setLocal(itemName, it.next()); this.stat.exec(env, scope, writer); forIteratorStatus.nextState(); if (ctrl.isJump()) { if (ctrl.isBreak()) { ctrl.setJumpNone(); break; } if (!ctrl.isContinue()) { return; } ctrl.setJumpNone(); } } if (this._else != null && forIteratorStatus.getIndex() == 0) { this._else.exec(env, scope, writer); } } private void forLoop(Env env, Scope scope, Writer writer) { Ctrl ctrl = scope.getCtrl(); Object outer = scope.get("for"); ForLoopStatus forLoopStatus = new ForLoopStatus(outer); scope.setLocal("for", forLoopStatus); Expr init = this.forCtrl.getInit(); Expr cond = this.forCtrl.getCond(); Expr update = this.forCtrl.getUpdate(); ctrl.setLocalAssignment(); init.eval(scope); for(; cond == null || Logic.isTrue(cond.eval(scope)); update.eval(scope)) { ctrl.setWisdomAssignment(); this.stat.exec(env, scope, writer); ctrl.setLocalAssignment(); forLoopStatus.nextState(); if (ctrl.isJump()) { if (ctrl.isBreak()) { ctrl.setJumpNone(); break; } if (!ctrl.isContinue()) { ctrl.setWisdomAssignment(); return; } ctrl.setJumpNone(); } } ctrl.setWisdomAssignment(); if (this._else != null && forLoopStatus.getIndex() == 0) { this._else.exec(env, scope, writer); } } }
3.编写分组标签GroupDirective代码:
import com.jfinal.template.Directive; import com.jfinal.template.Env; import com.jfinal.template.TemplateException; import com.jfinal.template.expr.ast.Expr; import com.jfinal.template.expr.ast.ExprList; import com.jfinal.template.expr.ast.ForCtrl; import com.jfinal.template.io.Writer; import com.jfinal.template.stat.Scope; import com.jfinal.template.stat.ast.ForIteratorStatus; import java.util.Iterator; /** * 分组标签 */ public class GroupDirective extends Directive { private Expr groupNumExpr; public GroupDirective() { } @Override public void exec(Env env, Scope scope, Writer writer) { if (groupNumExpr == null) { stat.exec(env, scope, writer); } else { Object groupNumObj = this.groupNumExpr.eval(scope); if (!(groupNumObj instanceof Integer groupNum)) { throw new TemplateException("group的第一个参数必须为int类型", this.location); } Object outer = scope.get("for"); if (outer instanceof ForIteratorStatus) { forIterator(env, scope, writer, groupNum, 0); } else { forLoop(env, scope, writer, groupNum); } } } private void forIterator(Env env, Scope scope, Writer writer, Integer groupNum, Integer flag) { this.stat.exec(env, scope, writer); ForIteratorStatus outer = (ForIteratorStatus) scope.get("for"); if (flag < groupNum - 1) { Iterator<?> it = (Iterator<?>) scope.get("forIterator"); if (it.hasNext()) { ForCtrl forCtrl = (ForCtrl) scope.get("forCtrl"); scope.setLocal(forCtrl.getId(), it.next()); scope.set("forIterator", it); scope.setLocal("for", outer); flag++; forIterator(env, scope, writer, groupNum, flag); } } } private void forLoop(Env env, Scope scope, Writer writer, Integer groupNum) { this.stat.exec(env, scope, writer); } // ExprList 代表指令参数表达式列表 public void setExprList(ExprList exprList) { int paraNum = exprList.length(); if (paraNum == 0) { this.groupNumExpr = null; } else { this.groupNumExpr = exprList.getExpr(0); } } public boolean hasEnd() { return true; } }
4.配置类中扩展#group指令
addDirective("group", GroupDirective.class);
5.编写模版代码举例:
#set(test=[1,2,3,4,5,6,7,8,9]) #for(item : test) <div style="width:100%"> #group(4) <span style="padding-right:10px">#(item)</span> #end </div> #end
6.最终渲染结果如下:
这个需求如果没有扩展确实还不太好实现