Scala / Lift - 试图理解 Lift 同时声明使用有效的 html 和 lift 的倾向:标签和渲染中的标签重写

发布于 2024-11-16 14:42:45 字数 3259 浏览 0 评论 0原文

所有七件事(http://seventhings.liftweb.net/)当然都很好,但我是特别热衷于模板 (http://seventhings.liftweb.net/templates) 中的声明“提升支持设计师友好模板。”

作为学习 Lift 做事方式的步骤之一,我尝试创建一个简单的对象创建形式:采用一些参数,将它们用作构造函数参数,然后将对象存放起来。经过一些研究和实验,我有两个担忧:

  1. 似乎有相当大的倾向在片段中显着重写/修饰模板标记。
  2. 表单似乎没有使用有效或可识别的 html 元素。

我的基础是:

表单示例/文档似乎都是关于特殊 lift: 标签。 探索 Lift 建议表单应如下所示:(http: //exploring.liftweb.net/master/index-6.html

<lift:Ledger.add form="POST">
  <entry:description />
  <entry:amount /><br />
  <entry:submit />
</lift:Ledger.add>

我不确定这是否是有效的 html5,虽然它可能是有效的 xhtml,但感觉这不符合您的精神对于我们的设计师来说,模板看起来就像真正的 html 朋友们。我在其他地方读过(无法再次找到它),我们确实可以选择使用实际的输入标签,但随后我们不会得到 Lift 的奇特形式接线或类似的某些部分,该段落不是很清楚关于我到底会错过什么,并且这些示例似乎对我编写纯 html 表单制作纯 html 帖子不感兴趣。

demo.liftweb.net 示例的代码 (1) 建议您的模板应如下所示 (2)

<lift:surround with="default" at="content">
  <div class="lift:PersonScreen"></div>
</lift:surround>

PersonScreen 代码段的代码也不完全具有启发性 (3)。还有一些模板的其他示例,例如,在特定位置仅具有 ul 标记,仅用于生成在片段中具有嵌套元素的一系列复杂的 li。当然,您可以在 Scala 中使用 xml,并且它的可读性还可以,但它仍然将您的标记分散到各处。这似乎违反了“设计师友好模板”的精神。

我想了解的内容。

长期以来,我在 Web 应用程序开发中严格遵循两条规则:

  1. “代码”(控制器、业务模型)中没有标记。
  2. 模板中没有任何业务逻辑。

Idiomatic Lift 似乎完全放弃了第一条规则,并完全忽略了第二条规则的价值。这些规则对我很有帮助,我不准备仅仅遵循那些似乎违反它们的示例,而不理解为什么它不会造成混乱。我想了解为什么 Lift 可以在代码片段中生成如此多的显示代码。我还想了解为什么模板中的标记很少反映输出是可以的。

我(认为我)想要的:

我希望我的模板中包含极少数(如果有的话)例外的所有标记。我希望我的代码片段进行最少的模板修改,通常只替换“叶子”标签上的元素文本,并可能调整属性值。我认为我已经为一个相当复杂的显示示例完成了此操作,并且我怀疑我可以使用相同的技术来生成普通的 html 表单,然后自己处理参数。如果我希望我的模板看起来像最终结果表单,这是我需要做的吗?

回复和任何其他想法,尤其是了解有关此内容的 Lift 心态的想法,将不胜感激。

谢谢!

  1. http://demo.liftweb.net/simple_screen?F674431078927QJVVYD=_
  2. https://github.com/lift/examples /blob/master/combo/example/src/main/webapp/simple_screen.html
  3. https ://github.com/lift/examples/blob/master/combo/example/src/main/scala/net/liftweb/example/snippet/Wizard.scala#L94

编辑

响应@OXMO456。 (感谢您的回复。)

我有,他们似乎只是证实了我的担忧:例如,我们从以下开始:

提升模板不包含可执行代码。它们是纯粹、原始、有效的 HTML。

这太棒了。然后后来:

后两种调用代码片段的机制不会产生有效的 Html5 模板。

然而每个人似乎都使用这两种机制中的第一种。另外,它还说:

第三,设计人员不必担心为了设计 HTML 页面而学习编程任何东西,因为程序执行是从 HTML 中抽象出来的,而不是嵌入到 HTML 中的。

但与我在 OP 中引用的示例片段非常一致的是,完全以编程方式生成标记。这似乎与以下目标背道而驰:(a) 拥有设计人员友好的模板,以便设计人员不必为 Freemarker 标记所困扰;(b) 将显示逻辑与业务逻辑分开。

第二个链接很有帮助且具有指导意义,但它很清楚地表明这不是电梯之路。然而,The Lift Way 似乎也将全部标记生成拖入片段中,(我认为)这是标记和业务逻辑的巨大复合。那是电梯路吗?

All of the Seven Things (http://seventhings.liftweb.net/) are certainly nice, but I was particularly enthusiastic about the claim in Templates (http://seventhings.liftweb.net/templates) that "Lift supports designer friendly templates."

As one of my steps in learning Lift's way of doing things I'm attempting to create a simple object creation form: take a few parameters, use them as constructor arguments, then stow the object away. After some research and experimentation, tho, I have two concerns:

  1. There seems to be a considerable propensity for significantly rewriting/embellishing the template markup in snippets.
  2. Forms don't seem to use valid or recognizable html elements.

What I'm basing this on:

The form examples/documentation seems all about special lift: tags. Exploring Lift suggests that a form should look like this: (http://exploring.liftweb.net/master/index-6.html)

<lift:Ledger.add form="POST">
  <entry:description />
  <entry:amount /><br />
  <entry:submit />
</lift:Ledger.add>

I'm not sure that's even valid html5 and while it might be valid xhtml, it doesn't feel like that meets the spirit of having your templates look like real html for our designer friends. I read somewhere else (can't find it again) that we did have the option of using actual input tags, but then we wouldn't get some parts of Lift's fancy form wire-up or somesuch, the passage wasn't very clear on what exactly I'd be missing out and the examples don't seem interested in my writing a plain html form making a plain html post.

The code for a demo.liftweb.net example (1) suggests that your template should look like this (2)

<lift:surround with="default" at="content">
  <div class="lift:PersonScreen"></div>
</lift:surround>

The code for PersonScreen snippet isn't exactly illuminating, either (3). There are several other examples of a template that has, e.g. only a ul tag in a particular location only to generate a whole series of complex li's with nested elements in the snippet. Sure, you can use xml in Scala and it reads tolerably, but it's still scattering your markup everywhere. This seems to violate the spirit of "designer friendly templates".

What I want to understand.

For a long time I've strictly followed two rules in my webapp development:

  1. No markup in 'code' (controllers, business models).
  2. No business logic in the templates whatsoever.

Idiomatic Lift seems to completely forego the first rule and completely miss the value of the second rule. These rules have served me well and I'm not ready to just follow along with the examples that seem to be violating them without understanding why its not going to create a mess. I want to understand why it's okay in Lift to have so much display code generated in the Snippets. I also want to understand why its okay that the markup in the templates so rarely reflects the output.

What I (think I) want:

I want all of my markup with very few, if any, exceptions to be in my templates. I want my snippets to do minimal template mangling, generally only replacing element text on "leaf" tags and possibly tweaking attribute values. I think I've done this for a reasonably complex display example and I suspect I could use the same technique to generate a vanilla html form and then handle the params myself. Is that what I need to do if I want my template to look like the end-result form?

Responses and any other thoughts, especially on understand the Lift mindset regarding this stuff, would be tremendously appreciated.

Thanks!

  1. http://demo.liftweb.net/simple_screen?F674431078927QJVVYD=_
  2. https://github.com/lift/examples/blob/master/combo/example/src/main/webapp/simple_screen.html
  3. https://github.com/lift/examples/blob/master/combo/example/src/main/scala/net/liftweb/example/snippet/Wizard.scala#L94

EDIT

In response to @OXMO456. (Thanks for the response.)

I have, and they seem to just confirm my concerns: E.g. we start with:

Lift templates contain no executable code. They are pure, raw, valid HTML.

which is awesome. Then later:

The latter two mechanisms for invoking snippets will not result in valid Html5 templates.

and yet everyone seems to use the first of those two mechanisms. Also, it says:

Third, the designers don’t have to worry about learning to program anything in order to design HTML pages because the program execution is abstracted away from the HTML rather than embedded in the HTML.

But pretty consistently the example snippets like the one I referenced in the OP generate markup entirely programmatically. This seems counter to the goals (a) of having designer friendly templates so the designers don't have to be bothered with Freemarker markup and (b) separating display logic from business logic.

The second link is helpful and instructive, but it makes it pretty clear that this isn't The Lift Way. However, The Lift Way also seems to drag a whole load of markup generation into snippets, which is (I think) a huge compounding of markup and business logic. Is that The Lift Way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

枯叶蝶 2024-11-23 14:42:45

这些是旧式标签,不是设计师友好的标签。

<lift:MySnippet>
  <b:field />
</lift:MySnippet>

结构

<div class="lift:MySnippet">
  <div class="field"></div>
</div>

旧式 Lift 模板是有效的 XML,而不是 XHTML - 所以你不能有未封闭的标签或任何东西 - 这将 Lift 与大多数框架区分开来,后者将模板视为原始字符串,其中的代码位始终交织在一起,而不考虑标签或 。

顺便说一句,在旧式标签中,这些字段都是捏造的 - 它们不是某些标准提升标签集的一部分。我可以很容易地做到:

<lift:MySnippet>
  <frobnicate:blorb />
</lift:MySnippet>

只要我的代码片段正在寻找该特定标签。

Lift 不允许您的模板中存在任何逻辑。所有逻辑都发生在您的 Snippet 类中。因此,对于上面的设计人员友好的示例,我可能有一个像这样的代码片段类:

 class MySnippet { 
   def render(in: NodeSeq): NodeSeq = ".field" #> Text("some text here")
 }

这将产生以下结果:

 <div>
   <div class="field">some text here</div>
 </div>

不可能将任何逻辑放入 Lift 模板中 - 他们所能做的就是调用 Lift 代码片段,它们是常规的 Scala 类,其中所有的工作发生。

Lift 放弃了实际代码中不应该有任何显示逻辑的规则。为什么?因为它可以产生更多可重用的代码,因为 Scala 具有内置于该语言中的强大 XML 支持,并且因为您的所有逻辑现在都被视为普通的旧 Scala 代码。

如果我定义一个名为 CurrentTime 的 Lift 代码片段,我可以简单地将其放入任何模板中,它将显示当前时间 - 使用老式 MVC 框架,每个操作方法都需要将时间设置为page 变量,然后我的模板需要修改才能打印出来。对于更复杂的逻辑,老式框架可能需要模板中的条件。 Lift 不允许这样做 - 您的所有逻辑都是常规 Scala 代码,适合重构,易于测试,并且与现代 IDE 兼容。

Those are old-style tags, not designer-friendly tags.

<lift:MySnippet>
  <b:field />
</lift:MySnippet>

becomes

<div class="lift:MySnippet">
  <div class="field"></div>
</div>

Old-style Lift templates are valid XML, not XHTML - so you can't have unclosed tags or anything - this differentiates Lift from most frameworks, which treat templates as raw strings with bits of code intertwined throughout, without regard to tags or structure.

BTW, in old-style tags, those fields are all fabricated - they aren't part of some standard set of Lift tags. I could just as easily do:

<lift:MySnippet>
  <frobnicate:blorb />
</lift:MySnippet>

as long as my snippet code is looking for that specific tag.

Lift doesn't allow any logic in your templates. All of the logic happens in your Snippet class. So for the designer-friendly example above, I might have a snippet class like this:

 class MySnippet { 
   def render(in: NodeSeq): NodeSeq = ".field" #> Text("some text here")
 }

which would yield this result:

 <div>
   <div class="field">some text here</div>
 </div>

It's impossible to put any logic in Lift templates - all they can do is invoke Lift snippets, which are regular Scala classes where all of the work happens.

Lift discards the rule that you shouldn't have any display logic in your real code. Why? Because it makes for more reusable code, because Scala has powerful XML support baked into the language and because all of your logic is now treated as plain old Scala code.

If I define a Lift snippet called CurrentTime, I can simply drop that in to any template and it will display the current time - with old-school MVC frameworks, each action method needs to set the time as a page variable and then my templates would need to be modified to print it out. For more complicated logic, old-school frameworks would probably require a conditional in the templates. Lift doesn't allow that - all of your logic is regular Scala code, eligible for refactoring, easily testable, and compatible with modern IDE's.

鸵鸟症 2024-11-23 14:42:45

在回答你的“我认为我想要什么”的问题时,你肯定可以做到这一点,没有问题。提升实际上就是选择和了解您的用例。通常,您在 Lift 中看到的示例会混合代码和标记,这当然是次优的。需要注意的重要一点是,从概念上讲,片段只是为了生成标记和渲染视图而设计的。

此外,由于 Lift 遵循其视图优先范例,视图实际需要的唯一东西是一个符号来概述您想要在哪些渲染片段中处理标记的哪些部分。有多种方法,如 OP 和“Bill”所示,但我个人更喜欢:

<div lift="YourSnippet.method">
  <p>Some other code</p>
</div>

这是更可取的,因为这样您就不会培养类属性(IMO),这可能会让设计者感到困惑。 Lift 对设计师来说非常友好,但我认为这里的主要问题是,在编写代码片段时必须遵守纪律,同时忽略当今许多混合了 Scala 和标记的示例。

您可能也对这篇文章感兴趣(http://blog.getintheloop.eu/2011/04/11/using-type-classes-for-lift-snippet-binding/);使用这种模式,您可以定义渲染逻辑的解耦、可重用部分,同时使您的业务逻辑安全地远离片段。

最后,我并不想无耻地推销我自己的产品,但我特意在 Lift in Action 的示例代码中不使用任何混合的 Scala xml 文字(除了说明它是可能的),所以也许它可能如果您正在查看 Lift ( http://manning.com/perrett/ ),将为您提供帮助

In answer to you're "what I think I want" question, sure you can do that no problem. Lift is really all about choices, and understanding your use case. Often the samples you see with Lift intermingle code and markup, which is of course sub-optiomal. The important thing to note is that snippets conceptually are solely designed to produce markup, and render the view.

In addition, as Lift follows its view first paradigm the only thing that the view actually requires is a notation to outline which sections of markup you want to process in which rendering snippets. There are several ways, as illustrate by both the OP and "Bill", but personally I prefer:

<div lift="YourSnippet.method">
  <p>Some other code</p>
</div>

This is preferable because you're then not culturing up the class attribute which (IMO) can be confusing for designers. Lift can be very designer friendly, but I think the main problem here is that you have to be both disciplined when writing your snippets whilst ignoring many of the samples available today which mix Scala and markup.

You may also be interested in this post ( http://blog.getintheloop.eu/2011/04/11/using-type-classes-for-lift-snippet-binding/ ); using this sort of pattern you can define decoupled, reusable parts of rendering logic whilst keeping your business logic safely out of the snippets.

Finally, and without wanting to shamelessly promote my own product, but I specifically went out of my way to not use any mixed Scala xml literals in my example code for Lift in Action (other than to illustrate that its possible), so perhaps it might be of assistance if you're looking at Lift ( http://manning.com/perrett/ )

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文