如何在使用 importmap 的 Rails 7 中安装 jQuery?

9

我有一个新的Rails 7应用程序。 我目前正在尝试学习自Rails 5以来所有的新功能。我想在我的javascript文件中使用以下代码,但是到目前为止,我得到了以下错误:未捕获的引用错误:$未定义

$(document).on("turbo:load", () => {
  console.log("turbo!");
});

这里有另外两个相关的文件。如果我需要发布其他东西,请告诉我。

importmap.rb

pin "application", preload: true
pin "jquery", to: "https://ga.jspm.io/npm:jquery@3.6.0/dist/jquery.js", preload: true
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
pin "el-transition", to: "https://ga.jspm.io/npm:el-transition@0.0.7/index.js"

pin_all_from "app/javascript/controllers", under: "controllers"

application.js

import "@hotwired/turbo-rails"
import "jquery"

$(document).on("turbo:load", () => {
  console.log("turbo!");
});
4个回答

19
只需切换到CDN而不是jspmjQuery将在导入时全局可用。
# config/importmap.rb

# NOTE: pin jquery to jsdelivr instead of jspm
pin "jquery", to: "https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.js"

// app/javascript/application.js

import "jquery"; // this import first
import "script"; // then your other imports that use `$`

// NOTE: don't use relative imports: `import "./script"`
//       add `pin "script"` to `importmap.rb`

console.log($); // ok

// app/javascript/script.js
console.log($)  // ok

一切都很顺利,一个导入,多个导入,jQuery插件。不需要额外的提升。
当使用jspm时,jQuery必须明确导入,就像其他模块一样,在需要的地方导入。
// app/javascript/place_where_i_need_jquery.js

import $ from "jquery";

// NOTE: don't make jQuery global, this only kind of works.
// window.$ = window.jQuery = $;

console.log($); // ok

为了澄清和解决关于“window”的问题。它与“stimulus”一起工作,因为控制器是通过动态的“import()”导入的,通常在jquery加载后并有时间将其分配给“window”,但这并不保证。这就是为什么你必须进行提升操作,确保在任何其他导入之前,“$”变成全局变量。

你的意思是不同的CDN会提供给我不同版本的某个包?比如说 ./bin/importmap pin jquery@3.6.3./bin/importmap pin jquery@3.6.3 --from jsdelivr 会给我不同版本的jquery吗?我觉得我一定理解错了什么,这似乎不太对。我感觉自己像疯了一样。 - Fred Willmore
哦,我明白了,它们非常不同。这对任何人有什么意义呢? - Fred Willmore
3
@FredWillmore jspm 是用于 ESM 模块的。由于模块的构建/初始化方式,$jQuery 不会被全局暴露。我猜还涉及一些额外的处理,因为这部分已经更改,不再是全局的 jQuery。(jsdelivr 也有 esm 选项,可以实现相同的功能)。 - Alex
投票支持这个。非常感谢! - undefined

7

按照其他答案的方法操作是可以解决问题的,但是当您固定新包时它将停止工作。

原因是所谓的JavaScript提升方式,这意味着它将重新排列你的代码以重新组织导入块。这会破坏jQuery窗口分配。

为了避免这种情况,提取代码

import jquery from "jquery"
window.jQuery = jquery
window.$ = jquery

将内容放在另一个文件中,并用单个导入语句调用它。

在我的情况下,我有:

application.js

import "./src/jquery"

$(function(){
  console.log("Hey!")
})

替换上述代码中的src/jquery.js为以上提供的代码。

2
这个答案的赞数较少,但它是更好的答案。即使有多个引脚,它也能正常工作。感谢分享! - Robert Reiz
1
当我尝试按照这个设置进行操作时,我遇到了一个GET http://localhost:3000/assets/src/jquery net::ERR_ABORTED 404 (Not Found)的错误。 - Tamik Soziev
@TamikSoziev 不要使用相对导入。你需要pin "src/jquery"import "src/jquery" - Alex

2

我需要在我的application.js文件中添加几行代码。

import "@hotwired/turbo-rails"
import jquery from "jquery"
window.jQuery = jquery
window.$ = jquery

显然,我们需要进行更多的设置才能使其正常工作?需要使用特定的 gem/js 包吗? - knagode

1
我尝试了这里的所有其他建议,但都没有起作用。
以下是解决方法:
  1. 引入 jQuery
    bin/importmap pin jquery

  2. 在 importmap.rb 中使用 jsdelivr.net 或本地文件
    由于某种未知原因,jspm 无法使用

    a) pin "jquery", to: "https://cdn.jsdelivr.net/npm/jquery/dist/jquery.js"

    b) pin "jquery", to: "jquery.js"
    如果使用本地文件,需要将 jquery.js 下载到 app/javascript/jquery.js

    您还可以固定到特定版本
    c) pin "jquery", to: "https://cdn.jsdelivr.net/npm/jquery@3.7.0/dist/jquery.js"

  3. 在 application.js 文件中只需添加以下内容
    import "jquery"

  4. 当您想在视图中使用 jQuery 时,需要在 script 标签上使用 type="module"

<script type="module">

 $(document).ready(function(){
   console.log($)
 })
</script>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接