【问题标题】:Inheriting layouts in Phoenix/Elixir在 Phoenix/Elixir 中继承布局
【发布时间】:2016-09-16 03:41:48
【问题描述】:

我需要为我的 Phoenix/Elixir 应用程序创建一个简单的布局层次结构,并从不同的布局继承我的模板。我知道如何为单个布局和多个模板做到这一点。但是我究竟如何才能从另一种布局继承一种布局呢?

比如说,层次结构是layout1 -> layout2 -> layout3 and template2(layout2), template3(layout3)。

在文档中没有提到这一点。

更新

基本布局是基本布局——类似于 OOP 中的基类,它不知道它的子布局——有多少,如果有的话。因此,从基数调用“render children1”是没有意义的。

【问题讨论】:

    标签: elixir phoenix-framework


    【解决方案1】:

    在调用渲染时,可以通过在assigns 中传递layout 键来嵌套布局:

    <%= render @view_module, @view_template, Map.put(assigns, :layout, {MyApp.LayoutView, "nested.html"}) %>
    

    这是Phoenix.View.render/3 文档中的相关部分

    分配

    分配是指将被 在模板中可用。但是,在分配下有一些键 由凤凰专门处理,分别是:

    • :layout - 告诉 Phoenix 将渲染结果包装在 给定的布局。请参阅下一节。

    以下assigns是保留的,不能直接设置:

    • @view_module - 正在渲染的视图模块
    • @view_template - 正在呈现@view_module 的模板## 布局模板可以使用:layout 选项在其他模板中呈现。 :layout 接受以下形式的元组
      {LayoutModule, "template.extension"}

    渲染模板 在布局中,只需使用 @view_module 调用 render/3@view_template 分配:

      <%= render @view_module, @view_template, assigns %>
    

    对于 3 种布局,您可以执行以下操作:

    # Controller
    render(conn, "index.html", nested_1: "nested_1.html", nested_2: "nested_2.html")
    
    # app.html.eex
    <%= render @view_module, @view_template, Map.put(assigns, :layout, {MyApp.LayoutView, assigns.nested_1}) %>
    
    # nested_1.html.eex
    <%= render @view_module, @view_template, Map.put(assigns, :layout, {MyApp.LayoutView, assigns.nested_2}) %>
    
    # nested_2.html.eex
    <%= render @view_module, @view_template, assigns %>
    

    【讨论】:

    • 您可以继续嵌套布局。您将在嵌套模板中进行相同的调用以嵌套另一个模板。您应该在最里面的模板中有&lt;%= render @view_module, @view_template, assigns %&gt;
    • You will have the same call to render in your nested template to nest another template. -- 我的基本模板不知道将嵌套哪些模板。
    • 你可以通过assigns传递它。例如在您的控制器中:render(conn, "index.html", user_layout: {MyApp.LayoutView, "user.html"}, other_layout: {MyApp.LayoutView, "other.html"})
    • 什么控制器?没有与布局关联的控制器。如果我有 20 个控制器,每个控制器有 20 个动作怎么办?
    • 大概你在某处有一个控制器。您还可以从插件中填充分配,我在这里使用了控制器操作来进行演示。不知何故,在您的应用程序的某个地方,您必须定义要使用的模板和布局。你的问题太抽象了,这是我目前能给你的最好答案。
    【解决方案2】:

    我解决这个问题的方法是在视图中添加一个帮助器来呈现父布局:

    defmodule MyApp.LayoutView do
      use MyApp.Web, :view
    
      def base_layout(conn, opts, do: contents) when is_list(opts) do
        render "base.html", [conn: conn, contents: contents] ++ opts
      end
    end
    

    帮助程序中的“内容”参数将是您放入 do/end 块中的任何内容,因此您可以在 HTML 中将其用于“子布局”,例如:

    <%= base_layout @conn, [foo: "bar"] do %>
    
        <div class="sublayout-wrapper">
          <%= render @view_module, @view_template, assigns %>      
        </div>
        <!-- specific footer for sub-layout goes here etc -->
    
    <% end %>
    

    在 base.html 布局中,我在需要渲染内容的地方输出 @contents 变量,例如:

    <html>
    <head>
        <title>My App</title>
    </head>
    <body>
        <div class="header"></div>
        <%= @contents %>
    </body>
    

    这有点小技巧,但到目前为止,这是我找到的解决问题的最佳方法。

    请注意,我还添加了一个 opts 参数,以便能够在特定情况下覆盖一些分配(我主要使用它来定义要附加到 &lt;html&gt;&lt;body&gt; 上的 html css 类,具体取决于正在呈现的子布局)。

    【讨论】:

    • 如果层次结构中有 4 个布局怎么办?意大利面条代码?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多