在Rails 7 (7.0.2.3)中安装jQuery时,我已经查找了尽可能多的帮助。我想在我的视图中的脚本标记中使用它,但我似乎无法将它导出到全局可用的地方,er...ANYWHERE。
当然,从安装和映射包的角度看,导入映射很容易操作。太棒了。在那之后,整个文档分崩离析,一种普遍的阴霾笼罩着使用js包的新方法。环顾四周,到处都是混乱。
尽管如此,我怎样才能添加这个或类似的内容:
import jquery from "jquery"
window.jQuery = jquery;
window.$ = jquery;以使这些全局函数工作,比如application.js。我希望在我所有的意见中都能得到$。
至于我所做的:
./bin/importmap pin jquery --download给我重要的地图线:
pin "jquery" # @3.6.0好的。然后查看导入映射JSON:
{
"imports": {
"application": "/assets/application-37a24e4747cc3cde854cbbd628efbdf8f909f7b031a9ec5d22c5052b06207eb8.js",
"@hotwired/turbo-rails": "/assets/turbo.min-96cbf52c71021ba210235aaeec4720012d2c1df7d2dab3770cfa49eea3bb09da.js",
"@hotwired/stimulus": "/assets/stimulus.min-900648768bd96f3faeba359cf33c1bd01ca424ca4d2d05f36a5d8345112ae93c.js",
"@hotwired/stimulus-loading": "/assets/stimulus-loading-1fc59770fb1654500044afd3f5f6d7d00800e5be36746d55b94a2963a7a228aa.js",
"jquery": "/assets/jquery-498b35766beec7b412bab57a5acbe41761daa65aa7090857db4e973fa88a5623.js",
"controllers/application": "/assets/controllers/application-368d98631bccbf2349e0d4f8269afb3fe9625118341966de054759d96ea86c7e.js",
"controllers/hello_controller": "/assets/controllers/hello_controller-549135e8e7c683a538c3d6d517339ba470fcfb79d62f738a0a089ba41851a554.js",
"controllers": "/assets/controllers/index-7a8fc081f7e391bd7b6fba95a75e36f88ba813da2c4c8787adad248afb9a0a06.js"
}
}阿丁。看来它就在那里。然后在application.html.erb中使用一个简单的脚本标记:
<script type="text/javascript" charset="utf-8">
$(document).ready(function (){
console.log('jQuery working.');
})
</script>失败。督察说:
(index):41 Uncaught ReferenceError: $ is not defined这看起来真的很基本,而且对于一些最常用的库中没有包含重要映射(如jQuery和Bootstrap )的文档来说是非常恼人的。
这是第一天的事情,但是文档在这些事情上是非常稀少的。似乎应该有一些协调一致的努力来真正解释webpack的改变,这本身就是另一个失败。
请,如果你知道答案,张贴它,这样每个人都可以受益。
谢谢。
发布于 2022-04-27 18:24:58
讨论
到目前为止(4月-2022年),有两件事需要考虑:内联脚本加载和浏览器导入地图支持。两者一起可以使内联脚本,其中引用通过导入地图定义的变量,反直觉性和容易出错。
内联脚本加载
内联脚本首先执行。这是在加载导入映射JS脚本之前。见MDN script docs。
浏览器Importmap支持
Importmap仍然非常新,支持也各不相同。这使事情变得复杂。
在没有导入地图支持的情况下,使用'DomContentLoaded'.
es-module-shim,它可以在 ' load‘+ 'DomContentLoaded’事件之后加载es-module-shim;Chrome的
结论
变量和函数提升机制处理脚本加载序列问题,但是在这种情况下,由于脚本是内联定义的,而导入映射脚本还没有加载,所以变量是未声明的,它将最终导致ReferenceError: ... is not defined。
解决方案
确保在访问之前定义了变量,方法是在运行代码访问之前检查导入映射中的脚本是否已加载到内联脚本和中。
最可靠的方法是将一个变量放入
application.js中,并在内联脚本中检查它的声明。如果存在,导入映射已经加载,application.js中的所有内容都存在于内联脚本上下文中。
document.DomContentLoaded事件或window.load事件或,这两个都可以与in关键字一起使用。或者,可以在custom event的末尾抛出一个application.js,以强制在导入映射代码加载之后才运行内联代码。
示例:
将jquery固定在importmap.rb
app/javascript/application.js中后的
// jquery does not export 'default' but defines window.$ and
// window.jQuery when loaded:
// - import 'jquery'; will not work
// - namespace does not matter here (jq)
// - no need to redefine it again w/ window.$ = jq.$
import * as jq from 'jquery';
// Define a variable to check in inlined HTML script
window.importmapScriptsLoaded = true;.erb.html / .html中的
注意到:根据注入的shims/poly填充,加载顺序可能仍未定义。在这种情况下,需要做更多的工作(比如抛出一个自定义事件)。另外,DOM可能会加载两次,这需要在代码不会被双重执行时考虑到。
<h1 id="hello">Hello</h1>
<script type="text/javascript">
// Guard against double DOM loads
var codeExecuted = false;
document.addEventListener('DOMContentLoaded', function(e) {
// Check if importmap stuff exisits without throwing an error.
// Then run main code w/ guard against multiple executions.
if ("importmapScriptsLoaded" in window) {
if (!codeExecuted) {
// Main code here
console.log($('#hello'));
// Don't forget to bump guard for one-time only JS execution !!
codeExecuted = true;
};
};
});
</script>public文件夹。这是不推荐的,原因有两个:内联脚本将加载到导入映射脚本之外。很可能内联一个脚本将导致内联它的所有依赖项。(这里尚未加载导入映射脚本)。示例:
<script type="text/javascript" src="/jquery.js"></script> https://stackoverflow.com/questions/71876873
复制相似问题