[英]Rails 7 (7.0.2.3) Importmap jQuery is not defined in view
關於在 Rails 7 (7.0.2.3) 中安裝 jQuery,我一直在尋找盡可能多的幫助。 我想在我的視圖中的腳本標簽中使用它,但我似乎無法將它導出到它在全球可用的地方,呃......任何地方。
就安裝和映射包而言,當然 importmaps 很容易操作。 太棒了。 在那之后,整個文檔都分崩離析,籠罩了這種使用 js 包的新方式。 環顧四周,一片混亂。
也就是說,我該如何添加這個或類似的東西:
import jquery from "jquery"
window.jQuery = jquery;
window.$ = jquery;
到 application.js 或任何地方讓這些全局函數工作,比如 $. 我希望在我的所有視圖中都可以使用 $。
至於我做了什么:
./bin/importmap pin jquery --download
給了我 importmap 行:
pin "jquery" # @3.6.0
好的。 然后查看importmap 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,這真的很煩人。
這是第 1 天的東西,但這些東西的文檔非常稀少。 似乎應該有一些協調的努力來真正解釋遠離 webpack 的變化,這本身就是另一場慘敗。
請,如果您知道此問題的答案,請發布它,以便每個人都可以受益。
謝謝。
截至目前(2022 年 4 月)有兩件事需要考慮:內聯腳本加載和瀏覽器 importmap 支持。 兩者一起可以制作內聯腳本,這些腳本引用通過 importmap 定義的變量,反直覺且容易出錯。
首先執行內聯腳本。 那是在加載 importmap JS 腳本之前。 請參閱MDN 腳本文檔。
Importmap 仍然很新,支持也各不相同。 這使事情復雜化。
es-module-shim
可以在 'load' + 'DomContentLoaded' 事件之后加載 importmap。變量和函數提升機制負責腳本加載順序問題,但在這種情況下,由於腳本是內聯定義的,而 importmap 腳本尚未加載,變量未聲明,它最終會導致ReferenceError: ... is not defined
。
通過檢查 importmap 中的腳本是否已加載到內聯腳本中以及在運行代碼訪問它們之前,確保在訪問之前定義了變量。
最可靠的是將變量放入
application.js
並在內聯腳本中安全地檢查其聲明。 如果存在,則 importmap 已加載,並且application.js
中的所有內容都存在於內聯腳本上下文中。
document.DomContentLoaded
事件或window.load
事件或兩者都可以與in
關鍵字一起使用。 或者,可以在application.js
的末尾引發自定義事件,以強制僅在加載 importmap 代碼后運行內聯代碼。
例子:
importmap.rb
中固定 jquery 后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;
.html
/ .erb.html
注意:根據注入的 shims/polyfill,加載順序可能仍未定義。 在這種情況下,需要做更多的工作(比如拋出自定義事件)。 此外,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
直接內聯相應的腳本。 不推薦這樣做有兩個原因: 內聯腳本將被加載到 importmap 腳本旁邊。 內聯一個腳本很可能會導致內聯其所有依賴項。 (這里還沒有加載 importmap 腳本)。例子:
<script type="text/javascript" src="/jquery.js"></script>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.