首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rails 7 (7.0.2.3)视图中未定义Importmap jQuery

Rails 7 (7.0.2.3)视图中未定义Importmap jQuery
EN

Stack Overflow用户
提问于 2022-04-14 19:42:54
回答 1查看 2.5K关注 0票数 4

在Rails 7 (7.0.2.3)中安装jQuery时,我已经查找了尽可能多的帮助。我想在我的视图中的脚本标记中使用它,但我似乎无法将它导出到全局可用的地方,er...ANYWHERE。

当然,从安装和映射包的角度看,导入映射很容易操作。太棒了。在那之后,整个文档分崩离析,一种普遍的阴霾笼罩着使用js包的新方法。环顾四周,到处都是混乱。

尽管如此,我怎样才能添加这个或类似的内容:

代码语言:javascript
复制
import jquery from "jquery"
window.jQuery = jquery;
window.$ = jquery;

以使这些全局函数工作,比如application.js。我希望在我所有的意见中都能得到$。

至于我所做的:

代码语言:javascript
复制
./bin/importmap pin jquery --download

给我重要的地图线:

代码语言:javascript
复制
pin "jquery" # @3.6.0

好的。然后查看导入映射JSON:

代码语言:javascript
复制
{
  "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中使用一个简单的脚本标记:

代码语言:javascript
复制
<script type="text/javascript" charset="utf-8">
        $(document).ready(function (){
            console.log('jQuery working.');
        })
</script>

失败。督察说:

代码语言:javascript
复制
(index):41 Uncaught ReferenceError: $ is not defined

这看起来真的很基本,而且对于一些最常用的库中没有包含重要映射(如jQuery和Bootstrap )的文档来说是非常恼人的。

这是第一天的事情,但是文档在这些事情上是非常稀少的。似乎应该有一些协调一致的努力来真正解释webpack的改变,这本身就是另一个失败。

请,如果你知道答案,张贴它,这样每个人都可以受益。

谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-27 18:24:58

讨论

到目前为止(4月-2022年),有两件事需要考虑:内联脚本加载和浏览器导入地图支持。两者一起可以使内联脚本,其中引用通过导入地图定义的变量,反直觉性和容易出错。

内联脚本加载

内联脚本首先执行。这是在加载导入映射JS脚本之前。见MDN script docs

浏览器Importmap支持

Importmap仍然非常新,支持也各不相同。这使事情变得复杂。

在没有导入地图支持的情况下,使用'DomContentLoaded'.

  • es-module-shim,它可以在 ' load‘+ 'DomContentLoaded’事件之后加载es-module-shim;Chrome的

  • 有导入地图支持,导入地图在 'load‘之前加载,而 DOM可能在’load‘之前加载两次

结论

变量和函数提升机制处理脚本加载序列问题,但是在这种情况下,由于脚本是内联定义的,而导入映射脚本还没有加载,所以变量是未声明的,它将最终导致ReferenceError: ... is not defined

解决方案

确保在访问之前定义了变量,方法是在运行代码访问之前检查导入映射中的脚本是否已加载到内联脚本和中。

最可靠的方法是将一个变量放入application.js中,并在内联脚本中检查它的声明。如果存在,导入映射已经加载,application.js中的所有内容都存在于内联脚本上下文中。

document.DomContentLoaded事件或window.load事件或,这两个都可以与in关键字一起使用。或者,可以在custom event的末尾抛出一个application.js,以强制在导入映射代码加载之后才运行内联代码。

示例:

将jquery固定在importmap.rb

  • In app/javascript/application.js

中后的

代码语言:javascript
复制
// 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可能会加载两次,这需要在代码不会被双重执行时考虑到。

代码语言:javascript
复制
<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>

  • Alternatively直接内联相应的脚本,可以使用asset pipeline,也可以直接插入public文件夹。这是不推荐的,原因有两个:内联脚本将加载到导入映射脚本之外。很可能内联一个脚本将导致内联它的所有依赖项。(这里尚未加载导入映射脚本)。

示例:

代码语言:javascript
复制
<script type="text/javascript" src="/jquery.js"></script> 
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71876873

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档