[英]How to use dynamic value with rails asset_path in javascript?
基於從 JavaScript 獲取資產路徑,我嘗試捕獲圖像的src
:
var icon = "1d0"
// ...
// some logic to get the right icon
// ...
var $icon = $("<img />", {
class: "day-check-icon",
src: "<%= asset_path('" + icon + ".png') %>"
})
顯然,它不會起作用,但它給出了我想要實現的目標。
假設它的(圖像)名稱存儲在 JavaScript 變量中,我如何動態渲染src
指向我的app/assets/images/
圖像?
就像你自己說的那樣,你的例子顯然行不通。 在我們進入解決方案之前,讓我簡要介紹一下原因。
問題很簡單,服務器在將文件發送到客戶端之前解析.erb文件的所有 ERB 代碼。 這意味着客戶端永遠不會看到 ERB 代碼,也無法與之交互。 您可以使用 ERB 代碼補充您的.js或.coffee文件,但反過來是不可能的。 您遇到的另一個問題與資產消化有關(默認情況下返回)。 服務器知道這些摘要文件路徑,但除非服務器提供信息,否則客戶端不知道。
外部資源( openweatherapi )也是如此,他們也不知道資產的消化是什么。 因此,當與來自客戶端的 JavaScript 的外部資源進行交互時,您需要某種方式將外部資源返回的資產路徑轉換為消化后的資產路徑。
最簡單的解決方案是關閉消化,但您可以在此處閱讀為什么通常應該打開消化。
假設您知道外部 API 總是請求特定資產。 也許您將 API 的圖像托管在自己的 Rails 服務器上,這樣您就不必依賴其他服務器(用於資產)。 假設您將圖像存儲在vendor/assets/images/openweatherapi
目錄中,因為它們是第三方的。 使用以下 JavaScript,您將為客戶端提供一個字典,以將普通資產名稱轉換為摘要資產名稱。
<% # lib/assets/javascripts/openweatherapi_assets.js.erb %>
<% # create a global variable assets if it doesn't exist already %>
var assets = assets || {};
assets.openweatherapi = assets.openweatherapi || {};
<% # go to path vendor/assets/images/openweather/* select all children that %>
<% # are a file and loop through each of them %>
<% Dir['vendor/assets/images/openweatherapi/*'].select(&File.method(:file?)).each do |path| %>
<% # the asset path doesn't include the (app|lib|vendor)/assets/images/ part %>
<% asset_path = path.sub('vendor/assets/images/', '') %>
<% file_name = File.basename(path) %>
<% # create the dictionary %>
assets.openweatherapi['<%= file_name %>'] = '<%= asset_path(asset_path) %>';
<% end %>
不要忘記在application.js 中包含您的 JavaScript 文件,最好在包含應用程序JavaScript 文件之前,以便您可以從一開始就使用該變量。 現在要從您的 JavaScript 中獲取已消化的資產路徑,只需在字典中搜索路徑即可。
var icon = "1d0.png";
var $icon = $("<img />", {
class: "day-check-icon",
src: assets.openweatherapi[icon],
});
另一個選項是在 AJAX 調用中將資產名稱發送到服務器,讓服務器為您提供正確的摘要資產路徑。 這通過執行以下操作非常簡單:
# config/routes.rb
Rails.application.routes.draw do
resources :assets, only: :index
end
# app/controllers/assets_controller.rb
class AssetsController < ApplicationController
def index
@name = params.require(:name)
end
end
# app/views/assets/index.json.jbuilder
json.name @name
json.path asset_path(@name)
<% # app/assets/javascripts/assets.js.erb %>
<% routes = Rails.application.routes.url_helpers %>
function getAsset(name) {
return Promise.resolve($.getJSON('<%= routes.assets_path %>', {name: name}));
}
同樣,確保該文件最好在依賴於getAsset
函數的任何文件之前包含在application.js 中。 然后您可以執行以下操作:
var icon = "1d0.png";
getAsset(icon).then(icon => {
var $icon = $("<img />", {
class: "day-check-icon",
src: icon.path,
});
});
請記住,您可以進一步優化 AJAX 方法,允許您通過單個請求獲取多個圖標路徑。 但這應該給你一個大致的想法。 還要記住,AJAX 調用會增加額外的嵌套和延遲,而這可以通過第一種方法避免。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.