javascript - 如何在javascript中使用带有railsasset_path的动态值?
问题描述
基于从 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
指向 my的图像?app/assets/images/
解决方案
就像你自己说的那样,你的例子显然是行不通的。在我们讨论解决方案之前,让我简要介绍一下原因。
问题很简单,服务器在将文件发送到客户端之前解析.erb文件的所有 ERB 代码。这意味着客户端永远不会看到 ERB 代码,也无法与之交互。您可以使用 ERB 代码补充您的.js或.coffee文件,但反过来是不可能的。您遇到的另一个问题与资产消化有关(默认情况下会返回)。服务器知道这些摘要文件路径,但客户端不知道,除非服务器提供信息。
外部资源(openweatherapi)也是如此,他们也不知道资产的消化是什么。因此,当您从客户端的 JavaScript 与外部资源交互时,您需要某种方法将外部资源返回的资产路径转换为摘要资产路径。
最简单的解决方案是关闭消解,但您可以在此处阅读为什么通常应该打开消解。
#1 预先提供资产路径
假设您知道外部 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],
});
#2 进行 AJAX 调用以获取资产路径
其他选项是在 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}));
}
同样,确保该文件包含在application.jsgetAsset
中,最好是在依赖于该函数的任何文件之前。然后您可以执行以下操作:
var icon = "1d0.png";
getAsset(icon).then(icon => {
var $icon = $("<img />", {
class: "day-check-icon",
src: icon.path,
});
});
请记住,您可以进一步优化 AJAX 方法,允许您通过单个请求获取多个图标路径。但这应该给你一个大致的想法。还要记住,AJAX 调用会增加额外的嵌套和延迟,而第一种方法可以避免这些。
推荐阅读
- python - 使用 pywin32 获取过去 3 个月内事件日志中所有错误条目的来源、日期/时间和消息的列表
- mysql - 带有 DATEDIFF 和 DATETIME() 或 NOW() 的 MySQL(或 Mariadb)表达式
- c - 从文件中删除尾随和前导空格
- php - cURL,如何添加这个特定参数?
- mysql - 如果列等于行,SQL 选择行
- angular - 获取资产文件夹中 txt 文件的请求 | 角 8
- gstreamer - v4l2src(c 应用程序)上的 nvidia deepstream
- swift - 如何在 Eureka 表单的多值行中访问 Delete Row 函数
- google-sheets - 包含 2 个电子表格的自定义公式条件格式
- php - json_decode 返回 null 并且 json_last_error 返回 JSON_ERROR_UTF16(错误 10),可能带有错误的表情符号