锁定老帖子 主题:对fastm的一些看法
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2005-06-03
fastm带来了开发上的突破当然在view层: .剥离页面逻辑给更擅长做逻辑的java去实现,解放html页面去做它该做的事:纯展示数据。 .借鉴php,使用html注释的方式标记动态部分,html开发view层所见即所得,美工和程序员一起合作出高质量的页面; .页面上没了逻辑,页面代码简洁漂亮,易于开发维护; 太美妙了!这才真正是mvc中view层开发的开端。 我这两天认真地看了下fastm的功能,觉得还有改进的余地: 因为页面没有逻辑判断,所以很多动态的html内容都要放到java中写。 比如奇偶行风格的问题。fastm是在类中定义了风格,但我认为这样显然html页面开发员是不能看到奇偶行的效果了。我认为奇偶是页面逻辑,但风格决不是,是静态页面就要看的出效果。 再比如另一个逻辑判断:true要对文字加href连接,false则显示纯文字,fastm的做法好像就只能把连接和文字都放进java类中,但这样做岂不是html页面没了连接?而且要改连接的style怎么办?改类?不合适吧? 我认为fastm的主要问题是把页面上所有的动态内容都认作是页面逻辑,统统放入类中作了实现。但我觉得动态内容还要细分:页面逻辑,展示逻辑。 比如日期的格式化展示,你在类中转好再放到页面?还是到页面再用某个格式化函数(当然fastm现在没有这样的函数)?我认为要延迟到页面作。因为要考虑一个valuset重用的问题,比如这个view1要求展示年月日,那个view2则要精确到时分秒,你要重用valueset就必须将这个转化逻辑放到页面作。我把这称为展示逻辑。 再来个例子,还是valueset重用的问题,比如你要valueset同时给html模版和产生pdf的fo模版使用,那你valueset里面的如" selected"," checked","styleclass",还有超连接标签等等对fo模版会有用么?没有。 再有就是代码擂台赛中的那个例子,因为页面没有逻辑判断能力,所以那个跨行显示学生各科目的成绩的实现,显得不够优雅。如果有了的话,我想如下面这样,不是很好么(其中size是每个学生的科目数)。 科目跨行的例子: <table border=1> <!-- BEGIN LIST: trs --> <!-- BEGIN LIST: subjects --> <tr> <!-- BEGIN IF: first --> <td rowspan="${size}">${name}</td> <td rowspan="${size}">${average_score}</td> <!-- END IF: first --> <td> ${subject} </td> <td> ${score} </td> </tr> <!-- END LIST : subjects --> <!-- END LIST : trs --> </table> 所以我认为页面针对bool值的展示逻辑如果用的好的话,不但不会破坏布局,相反可以使布局更完善。 改进意见: fastm拒绝了页面逻辑判断,认为这破坏了页面布局,我希望fastm引入逻辑分支,而且是完善的分支,当然我也不赞成在页面定义变量计算,所有if else分支需要的逻辑变量都应该在类里计算完成了,我管java计算这些逻辑值才是分离页面逻辑。但计算出的bool值html还要用,就如计算出的int值html也要用一样,比如true就出连接,fasle不出,比如true就选中checkbox,false就不选中,就如同是int就打印它的值一样,这是展示逻辑。这样的话我说的展示逻辑就到了html中了。引入了这种简单的对已计算好的bool值的判断,fastm的html页面才会显示更多它该显示的东西。不要怕这样会破坏页面布局,我这么试过,没有大的影响。 说了这么多,不知buaawhl认同多少?不定这么一改,fastm就真正的大放异彩了。我对fastm很有信心,对我的改进意见也是。:) 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2005-06-03
看到没有,看到没有,buaawhl要挺住呀,呵呵。
|
|
返回顶楼 | |
发表时间:2005-06-03
多谢 goldrain 的研究和分析。
正是这么多朋友的意见, 才迫使我做了很多fastm的改动,也推动了fastm的前进。以前,我为了直观和效率,坚持适用ValueSet。后来,也支持POJO的OGNL形式了,不一定要使用ValueSet。 说实话,goldrain 所阐述的问题,几乎都是 fastm 的死穴。 1. 尺寸、坐标参数 比如,那个代码擂台的例子,逻辑如此复杂。size都是参数,这时候fastm的“所见即所得”的优势都没有了。 还有另外一个例子。fastm处理HTML和Excel XML, 能够保持“所见即所得”的优势。但是对于绝对坐标的XDP (PDF的XML格式) ,如果需要动态创建多行控件,这时候要计算绝对坐标,坐标必须是参数,就不能保证“所见即所得”了。 2. 奇偶行风格问题 引用 比如奇偶行风格的问题。fastm是在类中定义了风格,但我认为这样显然html页面开发员是不能看到奇偶行的效果了。我认为奇偶是页面逻辑,但风格决不是,是静态页面就要看的出效果。 再比如另一个逻辑判断:true要对文字加href连接,false则显示纯文字,fastm的做法好像就只能把连接和文字都放进java类中,但这样做岂不是html页面没了连接?而且要改连接的style怎么办?改类?不合适吧? 这个问题应该这么解决,在更大的粒度上分块,而不是把color等作为参数。 <!-- BEGIN DYNAMIC: even --> <color="red"> <a href="">{name}</a> <!-- END DYNAMIC: even --> <!-- BEGIN DYNAMIC: odd --> <color="green"> {name} <!-- END DYNAMIC: odd --> 代码里面很简单。 if( isEven (i) ){ row.put("even", row); }else{ row.put("odd", row); } 3. 特殊UI相关数据问题 goldrain 写道 再来个例子,还是valueset重用的问题,比如你要valueset同时给html模版和产生pdf的fo模版使用,那你valueset里面的如" selected"," checked","styleclass",还有超连接标签等等对fo模版会有用么?没有。 这个问题我现在是这么解决的。比如: 公用的Domain Object,我定义为model. HTML特殊的view部分我定义为html. fo特殊的view部分我定义为fo. 在HTML里面我这么引用,{model.name.lastName}, {html.year.checkd} 在fo里面我这么引用,{model.name.lastName}, {fo......} 这个时候,html和fo特殊的部分,一定要不同的view逻辑来产生的。这个没有办法避免。用任何template都需要实现这两个不同的逻辑。 goldrain 写道 我认为fastm的主要问题是把页面上所有的动态内容都认作是页面逻辑,统统放入类中作了实现。但我觉得动态内容还要细分:页面逻辑,展示逻辑。 比如日期的格式化展示,你在类中转好再放到页面?还是到页面再用某个格式化函数(当然fastm现在没有这样的函数)?我认为要延迟到页面作。因为要考虑一个valuset重用的问题,比如这个view1要求展示年月日,那个view2则要精确到时分秒,你要重用valueset就必须将这个转化逻辑放到页面作。我把这称为展示逻辑。 这个也确实要实现两套逻辑。确实麻烦。 http://forum.iteye.com/viewtopic.php?t=13432&start=15 buaawhl 写道 fastm为了最大限度地支持“所见即所得”,不影响HTML正常显示。不得不放弃所有逻辑。这个也是衡量得失。而且,如果fastm在template中支持逻辑,函数调用,实现难度马上就上了一个台阶。 由于fastm的控制逻辑全部在java code里面,没有script。这就意味着,fastm的功能扩展,不用扩展script语法格式,直接扩展Java API就可以了。 我现在主要在这个方面下功夫。比如,提供了类似于OGNL的支持,为了大数据量情况下节省空间,提供了Iterator,ResultSet的支持,等。 你说的那些功能,都可以在fastm的外围API做。fastm也提供了类似于SAX Callback的机制,是一个IValueInterceptor, 匹配引擎每处理一个fastm template DOM Node的时候,都会调用这个IValueInterceptor。 特殊的需求,可以在这个IValueInterceptor里面实现。 比如,可以专门定义一个 FuncInterceptor处理{call.a.func(c, d)} 这样的东西。可以专门定义一个 FormatInterceptor处理{a.date@yyyy-mm-dd} 这样的格式处理。 其实,fastm的这种格式处理可以非常强大,可以根据 对象属性的名字、类型、值等,进行各种处理。 比如,beginDay, endDay, 就显示 yyyy-mm-dd; beginDay, endDay, 就显示 yyyy-mm; beginYear, endYear就显示 yyyy; beginTime, endTime 就显示 yyyy-mm-dd hh:mi:ss. 等。 这个我称为显示逻辑AOP。 多谢建议。这个方面,我打算大力加强 fastm的NodeInterceptor功能。 让用户可以处理上述的自定义标签格式。 写道 fastm拒绝了页面逻辑判断,认为这破坏了页面布局,我希望fastm引入逻辑分支,而且是完善的分支,当然我也不赞成在页面定义变量计算,所有if else分支需要的逻辑变量都应该在类里计算完成了,我管java计算这些逻辑值才是分离页面逻辑。但计算出的bool值html还要用,就如计算出的int值html也要用一样,比如true就出连接,fasle不出,比如true就选中checkbox,false就不选中,就如同是int就打印它的值一样,这是展示逻辑。这样的话我说的展示逻辑就到了html中了。引入了这种简单的对已计算好的bool值的判断,fastm的html页面才会显示更多它该显示的东西。不要怕这样会破坏页面布局,我这么试过,没有大的影响。 true和false我一直在考虑。是个好建议。多谢你的探讨。这方面我要多考虑考虑怎么实现。这个实现难度不大。比实现逻辑简单多了。:-) |
|
返回顶楼 | |
发表时间:2005-06-04
呵呵,又听到一个好消息,原来fastm已经支持对象属性访问了。
1.你说的坐标,尺寸等参数的确会影响"所见即所得"。的确,动态的部分如果变数 太大,当然不是静态内容能表述的,这点上其他模版语言也做不到的。而且引入 逻辑分支后,我相信会有所改观,就比如我举的那个跨行例子。这些情况在 开发中出现的比例不大(5%以下吧),遇到也并非不能解决,所以不必在意。 2.你对奇偶行的处理我看的有点奇怪,为了实现这么简单的概念(两种行风格),却用了我难以理解的技巧。觉得这么做其实也是对fastm页面不支持逻辑判断的一种“补丁”而已,已经背离了简洁的原则了。毕竟奇偶不是属于那5%的少数情况。还是要有更易于理解的方式来处理: <table border=1> <!-- BEGIN LIST : trs --> <!-- BEGIN IF : even --> <tr class="even"> <td> <input type=checkbox> even </td> <td> ${same} <td> <td> </td> </tr> <!-- ELSE --> <tr class="odd"> <td> <input type=checkbox disabled> noeven... </td> <td> ${same} <td> <td> </td> </tr> <!-- END IF : even --> <!-- END LIST : trs --> </table> 3.特殊UI相关数据问题 你认为还是特殊情况特殊处理。通过valueset里加变量来做,也未尝不可。 事实上我也觉得要完全避免valueset里写进类似" checked"," selected","styleclass"属性也不现实。但这些东西我认为还是展示逻辑,要尽量往页面放,让美工看到更多的页面效果,让我们的valueset尽量的干净:只承载数据和页面逻辑。 比如: <input type=checkbox {checked}> 这种写法问题不大,但我更倾向使用: <!-- BEGIN IF : canprocess --> <input type=checkbox name="code" value="{value}" checked> <!-- ELSE --> <input type=checkbox disabled> <!-- END IF : canprocess --> 虽然代码是多了点,但你要想到java代码会因此少很多:只要计算一个必须的逻辑值。注意看两个分支的不同,其中涉及的属性变化不是一个{checked}能概括的,如果你用java做会很复杂的。虽然这会导致html页面出来两个checkbox,但这对布局的影响是不大的,而且两种情况都在页面得到了展示。 呵呵,说不完道不尽,都是页面没有逻辑分支引起的,很高兴能看到buaawhl也对展示逻辑有了实现的兴趣。我想如果实现就实现的彻底点,不要像jstl那样死样怪气就一个c:if,连else都没有,我觉得要实现成java中if,else if,else的样子那才叫过瘾那,呵呵。当然,千万别做类似var1 == 1什么的布尔值运算实现,就一个bool值的true判断,false判断都不用,我认为!boolvalue就已经做了值运算了,而这应该在java中作,呵呵。 另外问个问题: 我的主贴那个跨行的例子:在first跨行时的两个值{name}和{average_score}不是subjects中的节点的,而是trs中的节点的变量。不知fastm支持否? 也就是问fastm支持逐层向上找父节点变量否?我觉得这很重要,就类似其它模版语言中的定义变量的作用范围一样,总希望子分支也能访问到。我希望fastm至少在valueset这样的数据结构中支持这种变量查找方式。不知buaawhl以为然否? |
|
返回顶楼 | |
发表时间:2005-06-04
goldrain 写道 2.你对奇偶行的处理我看的有点奇怪,为了实现这么简单的概念(两种行风格),却用了我难以理解的技巧。觉得这么做其实也是对fastm页面不支持逻辑判断的一种“补丁”而已,已经背离了简洁的原则了。毕竟奇偶不是属于那5%的少数情况。还是要有更易于理解的方式来处理: <table border=1> <!-- BEGIN LIST : trs --> <!-- BEGIN IF : even --> <tr class="even"> <td> <input type=checkbox> even </td> <td> ${same} <td> <td> </td> </tr> <!-- ELSE --> <tr class="odd"> <td> <input type=checkbox disabled> noeven... </td> <td> ${same} <td> <td> </td> </tr> <!-- END IF : even --> <!-- END LIST : trs --> </table> 3.特殊UI相关数据问题 你认为还是特殊情况特殊处理。通过valueset里加变量来做,也未尝不可。 事实上我也觉得要完全避免valueset里写进类似" checked"," selected","styleclass"属性也不现实。但这些东西我认为还是展示逻辑,要尽量往页面放,让美工看到更多的页面效果,让我们的valueset尽量的干净:只承载数据和页面逻辑。 比如: <input type=checkbox {checked}> 这种写法问题不大,但我更倾向使用: <!-- BEGIN IF : canprocess --> <input type=checkbox name="code" value="{value}" checked> <!-- ELSE --> <input type=checkbox disabled> <!-- END IF : canprocess --> 虽然代码是多了点,但你要想到java代码会因此少很多:只要计算一个必须的逻辑值。注意看两个分支的不同,其中涉及的属性变化不是一个{checked}能概括的,如果你用java做会很复杂的。虽然这会导致html页面出来两个checkbox,但这对布局的影响是不大的,而且两种情况都在页面得到了展示。 我上面给出的做法,就是你的这种思路阿。:-) <table border=1> <!-- BEGIN LIST : trs --> <!-- BEGIN DYNAMIC : even --> <tr class="even"> <td> <input type=checkbox> even </td> <td> ${same} <td> <td> </td> </tr> <!-- END DYNAMIC : even --> <!-- BEGIN DYNAMIC : odd --> <tr class="odd"> <td> <input type=checkbox disabled> noeven... </td> <td> ${same} <td> <td> </td> </tr> <!-- BEGIN DYNAMIC : odd --> <!-- END LIST : trs --> </table> 和你的写法差不多阿。 <!-- BEGIN DYNAMIC : canprocess --> <input type=checkbox name="code" value="{value}" checked> <!-- END DYNAMIC : canprocess --> <!-- BEGIN DYNAMIC : notprocess --> <input type=checkbox disabled> <!-- END DYNAMIC : notprocess --> 这个也是阿。而且这种方式,不仅能表达 if else. 而且能表达 if .. else if ... else if ... else. OO Design里面有这么一个教条(只是一个指导,而不是必须如此): 避免hard code条件分支 if..else if...else if...else, 或者switch. Martin Fowler的《企业架构模式》的 Template View 一章。 引用 Conditional Display A more knotty issue is conditional page behavior. The simplest case is the situation where something is displayed only if a condition is true. That might be some kind of conditional tag along the lines of <IF condition = "$pricedrop > 0.1"> ...show some stuff </IF>. The trouble with this is that when you start having conditional tags like this, you start going down the path of turning the templates into a programming language in and of themselves. This leads you into all the same problems you face when you embed scriptlets in the page. If you need a full programming language, you might as well use scriptlets, but you know what I think of that idea! As a result, I see purely conditional tags as a bad smell, something you should try to avoid. You can't always avoid them, but you should try to come up with something more focused than a general purpose <IF> tag. If you're displaying some text conditionally, one option is to move the condition into the helper. The page will then always insert the result of the call into helper. It's just that if the condition isn't true the helper will send back an empty string, but this way the helper holds all the logic. This approach works best if there's no markup for the returned text or it's enough to return empty markup that gets ignored by the browser. This doesn't work if, say, you want to highlight good-selling items in a list by putting their names in bold. In such a situation you always need the names displayed but sometimes you want the special markup. One way to get it is to have the helper generate the markup. This keeps all the logic out of the page, at the cost of moving the choice of highlighting mechanism away from the page designer and giving it to the programming code. In order to keep the choice of HTML in the hands of the page design, you need some form of conditional tag. However it's important to look beyond a simple <IF>. A good route to go is a focused tag, so rather than a tag that looks like this: <IF expression = "isHighSelling()"><B></IF> <property name = "price"/> <IF expression = "isHighSelling()"></B></IF> you have one like <highlight condition = "isHighSelling" style = "bold"> <property name = "price"/> </highlight> In either case it's important that the condition be done based on a single Boolean property of the helper. Putting any more complex expression into the page is actually putting the logic into the page itself. Another example would be putting information on a page that depends on the locale on which the system is running. Consider some text that should only be shown in the United States or Canada, which, rather than <IF expression = "locale = 'US' || 'CA'"> ...special text </IF> Would be something like <locale includes = "US, CA"> ...special text </locale> 可见Martin Fowler的想法 和我一样。避免IF, ELSE。 但是,Martin Fowler并没有找到一个好的解决方案,只是对这个方向做出了指导意见。 而fastm的思路则已经达到了这个地步。If, else, swith 等分支 Hash Map化。每个分支就是一个Key,每个Key对应一段Text,可以说,相当完美的解决了这个问题。 我觉得, 不必执著于早已受到大家深恶痛绝的IF-ELSE。:-) Martin Fowler后面的例子也表现出来了一种难以选择的困境. 是在HTML里面包含Code呢?还是在Code里面包含HTML? 其实没有给出解决方案。而fastm则给出了解决方案。 goldrain 写道 另外问个问题: 我的主贴那个跨行的例子:在first跨行时的两个值{name}和{average_score}不是subjects中的节点的,而是trs中的节点的变量。不知fastm支持否? 也就是问fastm支持逐层向上找父节点变量否?我觉得这很重要,就类似其它模版语言中的定义变量的作用范围一样,总希望子分支也能访问到。我希望fastm至少在valueset这样的数据结构中支持这种变量查找方式。不知buaawhl以为然否? This is a good point. 我一直在思考一个好的办法来支持{parent.parent.a.b}这样的向上回溯, 实现这个功能需要提供一个ContextObject,保存了当前的对象层次栈。 不过现在还没有支持。还没有想到一个简洁有效的好办法。 现在要使用上层对象,必须在构造Object DOM的时候,自己把parent reference加进去。比如,child.put("parent", parent); 这样,在下层就可以 {parent.name}来引用parent的name属性了。 |
|
返回顶楼 | |
发表时间:2005-06-04
如果我没理解错的话,<!-- BEGIN DYNAMIC : even --> 就是如果有even这个变量就展示,没有就忽略。
呵呵,有点理解你对奇偶行的处理思路了,很不错,将逻辑分支用map做。页面上if,else的写法的确没有这么做更简单,而且支持了多重分支。感觉模版引擎实现也比实现if,else简单点。厉害! 我考虑问题一般更侧重自己的使用方便,看来还是要多看看大师们的思想阿。 现在fastm的LIST和DYNAMIC都可以使用了么? 那这个跨行就可以实现为: <table border=1> <!-- BEGIN LIST: trs --> <!-- BEGIN LIST: subjects --> <tr> <!-- BEGIN DYNAMIC: tr --> <td rowspan="{tr.size}">{tr.name}</td> <td rowspan="${tr.size}">{tr.average_score}</td> <!-- END DYNAMIC: tr --> <td> ${subject} </td> <td> ${score} </td> </tr> <!-- END LIST : subjects --> <!-- END LIST : trs --> </table> 感觉不错,要在java代码里判断一下,在第一个科目的节点上放上父节点tr 挺灵活的,而且也不要求递归找父节点的变量了。 |
|
返回顶楼 | |
发表时间:2005-06-04
goldrain 写道 我考虑问题一般更侧重自己的使用方便,看来还是要多看看大师们的思想阿。 现在fastm的LIST和DYNAMIC都可以使用了么? 那这个跨行就可以实现为: <table border=1> <!-- BEGIN LIST: trs --> <!-- BEGIN LIST: subjects --> <tr> <!-- BEGIN DYNAMIC: tr --> <td rowspan="{tr.size}">{tr.name}</td> <td rowspan="${tr.size}">{tr.average_score}</td> <!-- END DYNAMIC: tr --> <td> ${subject} </td> <td> ${score} </td> </tr> <!-- END LIST : subjects --> <!-- END LIST : trs --> </table> 感觉不错,要在java代码里判断一下,在第一个科目的节点上放上父节点tr 挺灵活的,而且也不要求递归找父节点的变量了。 fastm把 List (for, loop, iterate), 和 choose (if, else, switch) 一样对待。都是用 DYNAMIC 来表示。 <table border=1> <!-- BEGIN DYNAMIC: trs --> <!-- BEGIN DYNAMIC: subjects --> <tr> <!-- BEGIN DYNAMIC: tr --> <td rowspan="{tr.size}">{tr.name}</td> <td rowspan="${tr.size}">{tr.average_score}</td> <!-- END DYNAMIC: tr --> <td> ${subject} </td> <td> ${score} </td> </tr> <!-- END DYNAMIC : subjects --> <!-- END DYNAMIC : trs --> </table> 如果对应的是一个Collection,Array, Iterator, ResultSet等,就根据其中的元素个数展开显示多次,否则就只显示一次。完全由Object DOM控制。:-) 所以,fastm的标签非常少。只有,BEGIN/END DYNAMIC, {} 两种。fastm1.0M出来了。 http://forum.iteye.com/viewtopic.php?t=13404 buaawhl 写道 http://blog.csdn.net/buaawhl/archive/2005/05/29/383491.aspx
buaawhl blog 写道 fastm 以前的 1.0 alpha 版本 https://sourceforge.net/projects/fastm fastm 1.0 Milestone 发布在java.net上。 https://fastm.dev.java.net/ 增强了很多功能。因为转移到java.net上,所以原来的package 名字 net.sf.fastm,改成 net.fastm. 在“Documents and Files”.可以下载 https://fastm.dev.java.net/servlets/ProjectDocumentList fastm1.0M, view adapter for SpringMVC, WebWork. 的源码,例子, 文档 https://fastm.dev.java.net/servlets/ProjectDocumentList?folderID=1552&expandFolder=1552&folderID=0 |
|
返回顶楼 | |
发表时间:2005-06-04
原来fastm已经支持了,能用map解决分支问题。看来我要求的页面逻辑是比较多余了。
一个标签解决所有动态问题,感觉是否太灵活了,呵呵。 这么简单的模版,俺是不会在乎多学一两个标签的。:) 为了我理想中的fastm,继续提需求,呵呵: 上面说到找父的问题,我想在valueset的组装时还是能通过将父设到子里解决这个访问问题。但对没有被组装过的POJO对象岂不是不行? 有个订单Order对象,Order有编号id属性,还有条目items属性(是List) 现在我要逐行打印条目,每个条目要打印出Order.id,应该怎么办。难道一定要重新组装个Pojo或valueset? 其实我的要求很简单:对动态内容节点给个key标记,这样访问才方便,你的current等隐含标记也可以省掉了。 比如: <table border=1> <!-- BEGIN DYNAMIC: tr in trs --> <!-- BEGIN DYNAMIC: subject in subjects --> <tr> <!-- BEGIN DYNAMIC: subject.first --> <td rowspan="{tr.size}">{tr.name}</td> <td rowspan="${tr.size}">{tr.average_score}</td> <!-- END DYNAMIC: tr --> <td> ${subject.name} </td> <td> ${subject.score} </td> </tr> <!-- END DYNAMIC : subjects --> <!-- END DYNAMIC : trs --> </table> 注意这里的subject.first,只要设置成一个非null值就可以了,DYNAMIC对非null值执行包含的块,对null则忽略。 这么做好像没有增加什么复杂度,我觉得语义更清楚了;而且也不需要你追溯找父,从实现讲也不难,只要维护一个map放key:value就可以了,这里的key就是tr,subject,每次要{var.prop}打印值,都从这个map去找key=var的value不就是了? 当然这样做最大的好处我觉得是省了大量的java组装view dom的代码。 订单item打印的例子就成了: <table border=1> <!-- BEGIN DYNAMIC: order --> <tr> <td colspan=2>{order.id}</td> </tr> <!-- BEGIN DYNAMIC: item in order.items --> <tr> <td> {order.id} </td> <td> {item.name} </td> </tr> <!-- END DYNAMIC: order.items --> <!-- END DYNAMIC: order --> </table> 对order对象根本就不用做重新组装了。不是挺好?:) |
|
返回顶楼 | |
发表时间:2005-06-04
goldrain 写道 为了我理想中的fastm,继续提需求,呵呵: 上面说到找父的问题,我想在valueset的组装时还是能通过将父设到子里解决这个访问问题。但对没有被组装过的POJO对象岂不是不行? 有个订单Order对象,Order有编号id属性,还有条目items属性(是List) 现在我要逐行打印条目,每个条目要打印出Order.id,应该怎么办。难道一定要重新组装个Pojo或valueset? 其实我的要求很简单:对动态内容节点给个key标记,这样访问才方便,你的current等隐含标记也可以省掉了。 比如: <table border=1> <!-- BEGIN DYNAMIC: tr in trs --> <!-- BEGIN DYNAMIC: subject in subjects --> <tr> <!-- BEGIN DYNAMIC: subject.first --> <td rowspan="{tr.size}">{tr.name}</td> <td rowspan="${tr.size}">{tr.average_score}</td> <!-- END DYNAMIC: tr --> <td> ${subject.name} </td> <td> ${subject.score} </td> </tr> <!-- END DYNAMIC : subjects --> <!-- END DYNAMIC : trs --> </table> 注意这里的subject.first,只要设置成一个非null值就可以了,DYNAMIC对非null值执行包含的块,对null则忽略。 这么做好像没有增加什么复杂度,我觉得语义更清楚了;而且也不需要你追溯找父,从实现讲也不难,只要维护一个map放key:value就可以了,这里的key就是tr,subject,每次要{var.prop}打印值,都从这个map去找key=var的value不就是了? 当然这样做最大的好处我觉得是省了大量的java组装view dom的代码。 订单item打印的例子就成了: <table border=1> <!-- BEGIN DYNAMIC: order --> <tr> <td colspan=2>{order.id}</td> </tr> <!-- BEGIN DYNAMIC: item in order.items --> <tr> <td> {order.id} </td> <td> {item.name} </td> </tr> <!-- END DYNAMIC: order.items --> <!-- END DYNAMIC: order --> </table> 对order对象根本就不用做重新组装了。不是挺好?:) 这是个好建议. :-) 和那个回溯, 属于同类问题. 我也一直在思索, 希望找到一个好的解决方案. Object回溯, Object Context, Object Map. 多谢你的深入思考。:-) 我在使用的过程中,也想到了这个问题。只是都想办法绕过去了。 这个一定要解决。是个很重要的功能。 其实,解决起来还是挺有难度的。Object Context如何传递,如何保存,保存那些值。等等。:-) thanks. |
|
返回顶楼 | |
发表时间:2005-06-04
buaawhl 写道 这是个好建议. :-) 和那个回溯, 属于同类问题. 我也一直在思索, 希望找到一个好的解决方案. Object回溯, Object Context, Object Map. 多谢你的深入思考。:-) 我在使用的过程中,也想到了这个问题。只是都想办法绕过去了。 这个一定要解决。是个很重要的功能。 其实,解决起来还是挺有难度的。Object Context如何传递,如何保存,保存那些值。等等。:-) thanks. 感觉没啥难度阿,在DYNAMIC开始时放入map,结束时从map去掉,而写页面的只要保证变量命名不要重复就行不是么。也不用考虑回溯问题了。可能我想的不够深入,呵呵 刚才订单的例子我改了下,觉得下面的做法更完善: <table border=1> <!-- BEGIN DYNAMIC: order --> <tr> <td colspan=2>{id}</td> </tr> <!-- BEGIN DYNAMIC: items --> <tr> <td> {order.id} </td> <td> {name} </td> </tr> <!-- END DYNAMIC: items --> <!-- END DYNAMIC: order --> </table> 就是引擎先在DYNAMIC直接作用的范围内找其所属变量或属性,不用使用变量名,就是现在fastm的做法,没找到时才用key去context map里找。 另外,我认真考虑下,觉得作为对bool单值判断if,else还是需要的,else if可能可以不要。没有了if,else,则我们valueset或pojo中的bool值对页面就失去了意义。没道理在页面放弃对bool值的控制阿,对现成的bool值还一定要到java中map一下,还是增加了java代码量。 比如再举个订单的例子,pojo中如果就有现成的字段isFreeze标识已冻结不能操作。我们没有必要放弃方便的直接将pojo扔给页面去展示,却组装一通map再放到页面,让页面直接判断这个freeze不挺好么。 当然你觉得if不可取可以不用或少用,但作为对最基础类型bool值的辨识能力,模版语言还是要具备的。我这么觉得,呵呵 |
|
返回顶楼 | |