簡體   English   中英

Rails 7 (7.0.2.3) Importmap jQuery 未在視圖中定義

[英]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 仍然很新,支持也各不相同。 這使事情復雜化。

  • 對於不支持 importmap 的 firefox,使用es-module-shim可以在 'load' + 'DomContentLoaded' 事件之后加載 importmap。
  • 對於支持 importmap 的 Chrome,importmap“load”和“DomContentLoaded”之前加載。
  • 此外,由於各種原因,DOM 可能會被加載兩次。

結論

變量和函數提升機制負責腳本加載順序問題,但在這種情況下,由於腳本是內聯定義的,而 importmap 腳本尚未加載,變量未聲明,它最終會導致ReferenceError: ... is not defined

解決方案

通過檢查 importmap 中的腳本是否已加載到內聯腳本中以及運行代碼訪問它們之前,確保在訪問之前定義了變量。

可靠的是將變量放入application.js並在內聯腳本中安全地檢查其聲明。 如果存在,則 importmap 已加載,並且application.js中的所有內容都存在於內聯腳本上下文中。

document.DomContentLoaded事件或window.load事件或兩者都可以與in關鍵字一起使用。 或者,可以在application.js的末尾引發自定義事件,以強制僅在加載 importmap 代碼后運行內聯代碼。

例子:

  1. importmap.rb中固定 jquery 后
  2. 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;
  1. .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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM