WebObjects/替代技术/Ruby on Rails
现实:如果你能获得文档,WebObjects 与 Ajax 的使用相对容易,只是目前只知道一个用于 Ajax-WO 支持的库,而且文档很少。即使如此,该库也只能做到这一步,它只是提供新的组件来包装一些 script.aculo.us 标签。
此外,WO 文档一直错误地引导用户使用组件操作而不是直接操作。
[也就是说,如果你避免使用 WO 的大部分功能,并且不使用组件操作,Ajax 会更容易。如果你确实使用了组件操作 - 我还没见过不用组件操作的项目 - 那么 Ajax 的使用似乎会清除你的页面缓存,如下所述。所以,在 WO 中使用 AJAX 真的很容易。真的很容易。只是它不起作用。]
[mschrag:虽然我同意上面评论者关于组件操作在 WO 中提供了强大功能的观点,但 Ajax 和组件操作并非不能兼容。Project Wonder 的 Ajax 组件 直接解决了在不清除页面缓存的情况下使用组件操作与 Ajax 的问题。虽然 Wonder 内部实现这些功能并非易事,但它证明了这种方法是可行的,如果你使用 PW 组件以及 ERXSession,你将免费获得此功能。]
我明确提到了这一点,因为最近有人问我这个问题,因为他们试图将一个 WYSIWYG JavaScript 编辑器附加到一个文本区域。
现实:实际上,真正发生的情况是,如果你在 WebObjects 中没有为你的 TextArea 指定 name=value 或 id=value 行,它会为你生成一个唯一的行。但你可以随意在你的 .wod 文件中指定一个,WO 会使用它。然后由你确保它的唯一性,这样你就不会有多个具有相同名称的文本区域标签。换句话说,如果你只有一个想要附加 JavaScript WYSIWYG 编辑器的文本区域,只需添加
textarea: WOText { id='wysiwyg'; name='wysiwyg'; value=textValue; }
到你的 .wod 文件中,你就可以在你的 JavaScript 中正常使用 id 了。
现实:仅仅因为你的 .wo 文件的组件是 .html 和 .wod 并不意味着 WebObjects 只能生成 HTML。WebObjects 实际上是一个非常非常复杂的 printf。组件的结果可以是 HTML、XML、JavaScript,甚至二进制数据。你实际上可以将任何内容放入 .HTML 中,并将 WebObjects 视为一个巨大的合并引擎。例如,你可以使用 WebObjects 生成 PDF 文件;它们只是文本,你可以很容易地将文本替换到 PDF 模板的中间。
[我保留了这个假设,但我考虑删除它,因为没有人关心 WO 能够生成一个混杂的 pdf 文件。人们关心像 GWT 这样的 Javascript 生成代码,而 WO 无法做到这一点。]
所以我做的第一件事是,我听说 Rails 很酷,而且可以轻松地使用 Ajax。我以前也听说过,但那是版本号为 0.13 的时候……所以我出去买了 Rails 书籍,你知道我发现了什么吗?
并不是 Rails 在 Ajax 上很厉害,而是 Prototype Javascript 库很厉害。文档花了很大篇幅介绍如何用一行代码实现 Ajax。
<div id='<= posting.id'>
<%= link_to_remote [div to update] [link options] -> %>
</div>
现实情况是,Rails 只做了一行 JavaScript 代码。从我添加到应用程序中的 Ajaxy "评分" 代码来看,请查看以下代码
<div id='<WEBOBJECT name=postingID></WEBBOBJECT>'>
<a href="#" onclick="new Ajax.Updater('<WEBOBJECT name=postingID></WEBBOBJECT>', '<WEBOBJECT name=ratePosting></WEBOBJECT>', {asynchronous:true, evalScripts:true}); return false;">1</a>
</div>
好的,让我们分解一下。从 Prototype 库来看,Ajax.Updater 的工作方式是,你给它一个 DOM 对象的 id 和一个 URL,它会用 URL 的内容替换具有该 id 的 DOM 对象。通常,你会使用一个 div 标签来指定要更新的区域,我已经为了完整性而展示了它。对于评分,我需要一个 div 标签来包含所有 5 个评分星
。我还会使用一个 WOGenericContainer 来生成具有正确 id 的 div 标签,而不是使用 id='<WEBOBJECT name=postingID></WEBBOBJECT>' 行,但我想让它很明显这是一个 div 标签。
因此,Ajaxy 部分是 <a> 标签,而不是 div 标签。
这里我有一个手动构建的 <a> 标签,带有一个 onclick 片段的 JavaScript 代码。它对 Prototype 库进行了一个单一的调用,该库有一个很酷的调用
new Ajax.Updater( elementid, url, options)
它做了一些非常简单的事情:它从指定的 URL 中拉取 HTML,并将具有指定 id 的元素替换为下载的 HTML。
两个 WebObjects 标签指定了元素 ID 和链接,它们只是 WOString 和 WOActionURL
postingID: WOString { currentPosting.primaryKeyString; } ratePosting: WOActionURL { see discussion }
现在在我的情况下,我是直接操作的狂热者。所以我的 WOActionURL 看起来像下面这样
ratePosting :WOActionURL { directActionName="PostingRater"; ?pkey=currentPosting.primaryKey; ?rating=cRating; ?wosid=NO; }
这会产生与 Rails 相似的结果,因为在 Rails 中,你必须为每一类链接定义一个操作。在我的情况下,我将直接操作与页面/组件绑定,所以我的 "PostingRater" 页面将返回与现有 <div> 定义相匹配的组件级 HTML(减去任何 HEAD/BODY 标签)。由于我们使用的是 WebObjects,如果我们用一个组件构建包含的 <div> 标签,这将变得非常容易,PostingRater 可以像下面这样
<WEBOBJECT name=RatingDiv></WEBOBJECT>
使用组件操作,它可以更简单
ratePosting: WOActionURL { action=ratePosting;}
因为 WebObjects 与 Rails 不同,它可以具有有状态的组件,所以 RatingDiv 组件实际上可以包含所有逻辑,并将自身作为操作的结果返回
public WOReponse ratePosting { currentPosting.ratePosting(currentRating); return self; // since this is called from JavaScript // return just myself, not self.page // this will tell WO to render only // this as a result. }
也就是说,JavaScript 的链接将进入 RatingDiv 组件,其中已经设置了所有内容:当前帖子、当前评分。然后返回自身会导致 div 重新生成。
但是,这里有一个问题,因为从 JavaScript 调用的组件操作会计入你的回溯计数。由于有人可能在页面上点击一个接一个的评分,这可能是一个问题。如果你的最大回溯计数是 10,而你页面上有 20 个帖子,他们将无法对第 11 个页面进行评分。
所以,Rails 有一行代码,而我有两行 WOTag,但这两行代码可以(也应该)通过创建一个 WODynamicElement 来直接生成链接而轻松组合起来。实质上,创建 "RemoteLink" WODynamicElement 来完成 Rails "link_to_remote" 调用所做的所有事情非常容易,即接收一个要更新的 id 以及 WOActionURL 所接受的所有选项。
但此外,WebObjects 解决方案在许多方面优于 Rails 解决方案。Rails 支持“部分页面”和“组件”,但现实情况是组件非常重量级/缓慢,而部分页面并不能完全实现您的预期。因此,WebObjects 解决方案通过将逻辑和状态都封装到组件中,最终比典型的 Rails 解决方案更 DRY(不要重复自己)并且封装性更好。在您需要 Ajax 部分的页面中,您指定组件,并将 Ajax 处理逻辑放在组件本身中。
我还没有在 Rails Ajax 支持中看到任何无法通过结合 WOComponents 和 WODynamicElements 在 WO 中轻松实现的功能。几乎所有 Rails 中的“Ajax 支持”都是 Prototype 中的一行代码。事实上,由于页面/组件可以具有状态,所以它可能比其他系统更容易在 WO 中完成。此外,我认为您可以构建一组提供比 Rails 更高级 Ajax 支持的 WOComponents。只是还没有人编写支持 WODynamicElements 或 WOComponents 的代码。
现在看看 Ahmet 的 dojo Hello World 示例,我不得不说,WebObjects 中没有任何东西阻止您这样做。本教程的 90% 是 JavaScript 代码,它不是针对任何特定技术。特定于 PHP/ASP/ColdFusion 的部分是在定义一个新页面,就像您在 WebObjects 中需要做的那样。只需在 Javascript 中使用 WOActionURL 替换 url: 即可。
我还认为,从这个例子来看,dojo 作为 Javascript 工具包有点弱。与 Prototype 相比,您将在 Dojo 中花费大量时间使用 Javascript 将内容连接起来。或者将 dojo 与 Yahoo UI 库进行对比
http://developer.yahoo.com/yui/
yui 中的整个“Dialog”功能非常酷
http://developer.yahoo.com/yui/container/dialog/index.html
并且非常容易适应 WO 在构建页面时使用部件的模型。
再说一次,dojo 只是 0.3 版本。所见即所得编辑器很好,但我真的不想用另一种标签语言定义我的对话框。HTML 对我来说已经足够了。
那么,您在 dojo/wo 中遇到了什么问题?请考虑问题可能是 dojo,而不是 WO 本身。您可以轻松地为每个新的 dojo 标签创建一个 WODynamicElement,将它们收集到组件中,并创建比直接使用 dojo 更容易使用的东西。