<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 3.1 布局和輔助方法 ## 概要: 本課時講解Rails 視圖(View)中的布局文件,常見的輔助方法(Helper)以及如何使用局部模板。 ## 知識點: 1. 布局(layout) 1. 輔助方法(helper) 1. 局部模板(partial) ## 正文 ### 3.1.1 布局(layout) 本章開始,我們將進入 Rails 的視圖(view) 的開發中。如果你對 Rails 這個 MVC 框架還有一些模糊的話,建議讀一讀[這篇文章](http://www.ruanyifeng.com/blog/2007/11/mvc.html)。 > Rails 是一個 RESTful 風格的 MVC 框架。 我們把第一章使用 bootswatch 創建的項目 copy 過來。現在,我們進入到 `app/views` 這個文件夾吧。 `layouts` 里放的是布局文件。如果我們網站只有一種布局,那么一個 `application.html.erb` 就足夠了。我們也可以為每個資源創建一個 `layout`,比如 `app/views/layouts/products.html.erb`。 我們刪掉多余的代碼,增加一個 `yield` 的輔助方法(helper)。 ~~~ <div class="container"> <%= yield %> </div> ~~~ 訪問我們的[頁面](http://localhost:3000/),希望你會看到和我一樣的效果。如果沒有,沒關系,可以到 [這里](https://github.com/liwei78/rails-practice-code) clone 我們的代碼。 ![](https://box.kancloud.cn/2015-08-18_55d2e47f7f39a.png) `yield` 方法可以讓 Rails 使用我們的模板(template) `app/views/products/index.html.erb` 填充了布局(layout)。 我們再看一下 `app/views/layouts/application.html.erb` 中的這一行: ~~~ <%= yield(:page_stylesheet) if content_for?(:page_stylesheet) %> ~~~ 如果我們在 `app/views/products/index.html.erb` 中使用 `content_for` 方法,可以在這個layout 的這個位置,顯示額外的內容,比如,我們在 `index.html.erb` 的最上面增加: ~~~ <%= content_for :page_stylesheet do %> <!-- 這是 index.html.erb 里單獨使用的 --> <% end %> ~~~ 再刷新下[頁面](http://localhost:3000/),我們在源碼里看到: ![](https://box.kancloud.cn/2015-08-18_55d2e47f935e0.png) 在實踐開發里,我們經常這樣做:布局中加載的是所有頁面通用的內容和 css,js,而到了具體頁面,就通過 `content_for` 這個輔助方法定義自己的內容,在我們的 `application.html.erb` 里,你可以找到四個 `content_for`,這樣給我們的代碼里增加了一些靈活,也不必把所有內容都寫到一起。 `content_for?` 判斷我們是否定義了這個變量。 如果我們想更改一下布局,該如何做呢?實踐中,我們的確會遇到以下幾種情形: #### 情形一:admin 要使用自己的布局文件 `app/views/layouts/admin.html.erb` 我們在 admin 的 controller 里聲明它使用另一個: ~~~ class AdminController < ApplicationController layout "admin" ~~~ 通常我們把 admin 放到 module 中,而為 admin 建立一個通用的 controller,讓所有 admin 的 controller 都繼承它,這樣,我們不用反復的去定義了: ~~~ class Admin::BaseController < ApplicationController layout "admin" end class Admin::ProductsController < Admin::BaseController end class Admin::CommentsController < Admin::BaseController end ~~~ #### 情形二:為完成某個特殊操作,我們需要更改布局。 這時,我們要在 action 里去變更這個布局,比如,創建一個 Product 的時候: ~~~ def new @product = Product.new render layout: "another_layout" end ~~~ #### 情形三:不用布局 ~~~ def edit render layout: false end ~~~ ### 3.1.2 常用的輔助方法(helper) 上一節,我們已經使用了幾個輔助方法,這里我們再介紹幾個 [Layouts and Rendering in Rails](http://guides.rubyonrails.org/layouts_and_rendering.html) 提到的 helper。 #### link_to 你會發現在頁面里最多的是 link_to 這個方法,它的參數也是蠻多的,我們來詳細講解。 我們把現在的 view 修改一下,把 `首頁` 的鏈接加上。 ~~~ <%= link_to "網店演示", root_path, class: "navbar-brand" %> ~~~ 一個稍復雜的例子: ~~~ <%= link_to "刪除", product, :method => :delete, :data => { :confirm => "點擊確定繼續" }, :class => 'btn btn-danger btn-xs' %> ~~~ 我們可以改變 `link_to` 的默認行為(GET),`:method => :delete` 將發送 `delete` 請求。`:confirm` 將會告訴瀏覽器阻止我們當前的動作,直到點擊 `確定`。實現上面兩個效果,需要引入 `ujs`, 在我們的 `app/assets/javascripts/simplex.js`[1] 中已經為我們引入了: ~~~ //= require jquery //= require jquery_ujs ~~~ 注[1]:通常我們使用的是 `application.js`,但是在 1.3 中我們設計了新的主題,目前我使用的是 `simplex`。 寫到這里,我要推薦 [http://api.rubyonrails.org/](http://api.rubyonrails.org/) 這里了,對于各種 Rails 本身的方法,我們可以通過查詢 api 文檔得到。如果是某個 Gem 提供的方法,我們可以直接翻看它的 README 或者代碼。 一個較實用的工具 Dash,可以幫你管理每個版本 api 文檔,查詢起來也很方便。不過它是收費的。 ![](https://box.kancloud.cn/2015-08-18_55d2e47fa113e.png) #### image_tag 建議你使用 api 文檔查找一下這方法,你會看到這個代碼提示: ~~~ image_tag("icon") # => <img alt="Icon" src="/assets/icon" /> image_tag("icon.png") # => <img alt="Icon" src="/assets/icon.png" /> image_tag("icon.png", size: "16x10", alt: "Edit Entry") # => <img src="/assets/icon.png" width="16" height="10" alt="Edit Entry" /> image_tag("/icons/icon.gif", size: "16") # => <img src="/icons/icon.gif" width="16" height="16" alt="Icon" /> image_tag("/icons/icon.gif", height: '32', width: '32') # => <img alt="Icon" height="32" src="/icons/icon.gif" width="32" /> image_tag("/icons/icon.gif", class: "menu_icon") # => <img alt="Icon" class="menu_icon" src="/icons/icon.gif" /> ~~~ 我們的圖片是來自 `app/assets/images` 的,我放了一個 `logo.png` 在里面,你會發現它的地址是:`http://localhost:3000/assets/logo-be2e3e66a18126c4042f84cd4aae4cb3.png`。Rails 使用 [sprockets-rails](https://github.com/rails/sprockets-rails) 來管理 `app/assets` 中的文件,后面章節我們會詳細介紹。 這里,我們可以關閉 `be2e3e66a18126c4042f84cd4aae4cb3`這種形式: `config/environments/development.rb` ~~~ config.assets.digest = false ~~~ 重啟我們的服務,地址變為 `http://localhost:3000/assets/logo.png`。 #### auto_discovery_link_tag 我們經常在 `head` 里和頁面里,增加 rss 和 atom 訂閱連接,這時,我們可以使用 `auto_discovery_link_tag` 這個輔助方法。 ~~~ <head> ... <%= auto_discovery_link_tag(:rss, {controller: "products", action: "index"}, {title: "RSS Feed"}) %> <%= auto_discovery_link_tag(:atom, {controller: "products", action: "index"}, {title: "ATOM Feed"}) %> ... </head> ~~~ 我們也可以在頁面中增加這個連接,這在 web2.0 興起后的博客中很常見,方便我們把數據加入到訂閱中。 ~~~ <%= link_to "rss", products_url(format: "rss") %> <%= link_to "atom", products_url(format: "atom") %> ~~~ 剩下的問題是, Rails 如何提供這個數據,我并不想等到 controller 里再去講這個部分,讓我們現在開始了解下: > Rails 是會根據我們的請求類型,做出響應。 如果我們請求的是一個 `http://localhost:3000/products.html`,Rails 會給我們 html 的頁面,而如果我們請求的是 `http://localhost:3000/products.rss`,Rails 會自動選擇 rss 的模板,渲染(render)后返回我們結果。`http://localhost:3000/products.atom` 也是一樣。 所以,我們在 `app/views/products/` 中增加兩個文件:`index.rss.builder` 和 `index.atom.builder`。 在 controller 里,如果我們想對結果做一些其他的操作,就需要增加這個代碼: `app/controllers/products_controller.rb` ~~~ respond_to do |format| format.html format.rss { ... } format.atom { ... } end ~~~ 在這個例子中,我們并不需要改變什么,所以不用添加它。 `app/views/products/index.atom.builder` ~~~ atom_feed do |feed| feed.title "商品列表" feed.updated @products.maximum(:updated_at) @products.each do |product| feed.entry product, published: product.updated_at do |entry| entry.title product.name entry.content product.description entry.price product.price end end end ~~~ `app/views/products/index.rss.builder` ~~~ xml.instruct! :xml, version: "1.0" xml.rss version: "2.0" do xml.channel do xml.title "商品列表" xml.description "這是商品列表" xml.link products_url @products.each do |product| xml.item do xml.title product.name xml.description product.description xml.price product.price xml.link product_url(product) xml.guid product_url(product) end end end end ~~~ 再次訪問 `http://localhost:3000/products.rss` 和 `http://localhost:3000/products.atom`,你會發現我們得到了結果。 我們用到了 `.builder` 這個結尾的文件,它會告訴 Rails 使用 `Builder::XmlMarkup` 這個庫(lib)來解析文件。所以看 `rss.builder`,它是按照 xml 格式寫的。`atom.builder` 用到了另一個輔助方法 `atom_feed`,寫法雖然不同,但是生成的內容也是 xml 格式的。 在 `scaffold` 創建的文件里,你會看到 `index.json.jbuilder`,它會使用 `JBuilder` 這個庫來解析并生成 `json` 的結果。這會在后面的章節講到,你可以在 [這里](https://github.com/rails/jbuilder) 先了解一下。 Railscasts.com 是所有 Rails 學習者必看的網站,這個 [視頻](http://railscasts.com/episodes/87-generating-rss-feeds-revised) 一定會幫助你理解上面的內容。 在此,向 Ryan 致敬。 #### stylesheet_link_tag ~~~ <head> <%= stylesheet_link_tag "simplex", :media => "all" %> </head> ~~~ css 文件的引用通常放到頁面的 `head` 標簽之間。這里我們引用的是 css 文件,我們也可以把它改為 `.css.scss`,這樣可以在里面寫一些 `scss` 語法,而不用更改我們的引用。我們在 `2.1.3` 中已經提到了 `scss`。 #### javascript_include_tag ~~~ ... <%= javascript_include_tag "simplex" %> <%= yield(:page_javascript) if content_for?(:page_javascript) %> </body> ~~~ 瀏覽器是自上而下解析節點元素(DOM)的,所以,請注意我們把 `js` 文件加載放到頁面最下面,以免因為某個 js 解析問題導致頁面始終無法顯示。在引用完 `js` 庫后,我們還可以根據需要,單獨放置頁面的 `:page_javascript`。 ActionView 還為我們提供了其他很多輔助方法,可以查看 [這里](http://guides.rubyonrails.org/action_view_overview.html#overview-of-helpers-provided-by-action-view)。 ### 3.1.3 局部模板(partial) > DRY, Don't Repeat Yourself.不要重復自己。 為了讓我們節省更多的頁面重復代碼,我們還可以使用局部模板(partial)。打開我們的 `app/views/products/index.html.erb`: ~~~ <% @products.each do |product| %> <%= render partial: "product", locals: { product: product } %> <% end %> ~~~ 這里我們使用了局部模板,`partial` 指定了使用哪個模板,`locals` 向模板里傳遞了一個變量。在 `_product.html.erb` 里,我們顯示具體 `product` 的信息。 不過這是一個老套的寫法,Rails 4 給了我們更酷的寫法: ~~~ <%= render @products %> ~~~ 不過,如果需要傳遞更多的變量(locals),還是要用第一種方法,當然,你完全可以把 `each do` 的代碼放到局部模板里。 我們也可以不傳遞變量到局部模板里,它可以找到 `@products`,看一下 `new.html.erb` 和 `edit.html.erb`: ~~~ <%= render :partial => 'form' %> ~~~ 也可以直接寫: ~~~ <%= render 'form' %> ~~~ 如果我們在頁面加載路徑中,放置了多個同名的局部模板,它會顯示離它最近的那個。我們可以把公用較多的模板,放到一個專屬的文件夾里,比如 `shared`,引用的時候: ~~~ <%= render partial: "shared/product", locals: { product: product } %> ~~~ 注:當使用 `locals` 傳遞參數時,一定要聲明 `partial`。 我為大家在 `shared` 中放置了一個同樣的 `_product.html.erb`,大家可以在 `index.html.erb` 中調用看看。 說一個實踐中經常用到的局部模板。 我建立了一個新的文件夾 `application`,這里會放布局文件使用的局部模板,我放了一個 `_flash.html.erb`,這是 `flash` 通知。看看我們的 `products_controller.rb`,我們在操作成功后會有提示信息,它在我們的頁面上還沒有顯示。我修改了一下 `application.html.erb`: ~~~ <div class="container"> <%= render "flash" %> <%= yield %> ... ~~~ 為了讓 `flash` 符合 `bootstrap` 的格式,我做了代碼調整,大家可以參考代碼。`flash` 是 session 的應用,通常在 controller 的 `action` 間傳遞信息,讀取成功后自動清空。如果一個 flash 沒有在合適得地方讀出來,那么它將被保存到讀出為止,這會造成本不該顯示它的地方卻顯示它,所以我把 `flash` 放到了 `layout` 中,使得所有頁面都會引用它,保證它產生后立刻顯示,并在顯示后自動清空。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看