如何从 rails 5.1.3 + webpacker 的视图中使用 jquery

How to use jquery from views on rails 5.1.3 + webpacker

我想像这样使用一个简单的 jQuery 函数:

$( document ).ready(function(){
    $('body').addClass("faded");
  });

来自 rails 5.1.3 应用程序的单个视图,在本例中为 'login.html.erb'

在 webpack 的 application.js 我有:

var $ = require('jquery');

如果我把它放在同一个 application.js 文件中,这使得前面提到的 jquery 调用工作,但这意味着它会被所有页面调用,因为 <%= javascript_pack_tag 'application' %> 在布局上。

当我像这样在 login.html.erb 上尝试 运行 时:

<script type="text/javascript">

$( document ).ready(function(){
    $('body').addClass("faded");
  });
</script>

我在控制台上收到错误消息:"ReferenceError: $ is not defined"。

如果我尝试在 login.html.erb 文件上执行 " import $ from 'jquery'; ",我会收到此错误:"SyntaxError: import declarations may only appear at top level of a module"这可以理解意味着我的本地 .erb 视图无法访问 webpacker 的 application.js 上引用的 javascript 并且无法从那里导入它。

如何从视图中引用 jquery 以及 webpacker 提供的任何模块?

如果之前有人问过这个问题,我深表歉意,在阅读了几天有关 webpack、webpacker gem 和 javascript 的文章后,我没有找到解决方案,因此发布了这个问题。

:)

要事第一。您不能使用 webpacker 在脚本标签内的 erb 模板中转换 es6。

自从在 rails 中引入资产管道以来,总体思路是交付多个 javascript 文件的捆绑包。在 webpacker 之前通过定义 sprockets 清单,现在使用 packs。这允许保存对 js 资产文件的 http 请求。浏览器在对应用程序的第一个 http 请求中只加载一个包含所有 javascript 的文件,并缓存它以供进一步的页面请求。

因此,您可以为应用程序的各个部分定义单独的 js 文件,并将所有文件导入 application.js 包中。只能通过 javascript_include_tag 包含包文件。您还必须在每个导入的 es6 模块中导入 jquery,因为 es6 模块有自己的变量范围。 (只需检查 chrome 开发工具中的转译输出)

但是现在,您不能只在 body 上调用 addClass,因为您只希望它发生在登录页面上。一种解决方法是在 erb 模板中设置一个单独的 class(例如“.login”)并将其用作 selector。

//app/javascript/packs/application.js
import 'startpage'
import 'login'

//app/javascript/src/login/index.js
import $ from 'jquery'
$('.login .content').addClass("faded");

如果 faded 确实必须添加到正文中(不在模板中),您可以通过“.login”class 中的父匹配器尝试 select 或以某种方式引入rails 布局中的一个变量,它是从 erb 模板中设置的,以便为布局添加控制器特定标记。

当然,如果您认为这不会产生很多 http 请求并且速度对您的用户来说足够好,您也可以为每个页面提供一个单独的 js 文件。只需在 packs 文件夹中将它们全部制作成单独的包文件即可。

  1. 安装jQuery/bin/yarn add jquery
  2. 打开 config/webpack/shared.js,然后 add/overwrite 使用此代码:

    module: {
      rules: sync(join(loadersDir, '*.js')).map(loader => require(loader)),
    
      noParse: function(content) {
        return /jquery/.test(content);
      }
    },
    
    plugins: [
      new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(env))),
      new ExtractTextPlugin(env.NODE_ENV === 'production' ? '[name]-[hash].css' : '[name].css'),
      new ManifestPlugin({
        publicPath: output.publicPath,
        writeToFileEmit: true
      }),
      new webpack.ProvidePlugin({
        $: "jquery",
        jQuery: "jquery",
        "window.jQuery": 'jquery',
      }),
    ],
    
    resolve: {
      extensions: settings.extensions,
      modules: [
        resolve(settings.source_path),
        'node_modules'
      ],
    
      alias: {
        jquery: 'jquery/dist/jquery.slim.js',
      }
    },
    

    你可能想要完整的 jQuery,而不是 jQuery 苗条

  3. 将jQueryglobal.$ = require('jquery')导入app/javascripts/packs

  4. 上的任何js文件

现在可以使用了

$(document).ready(function() {
  //
});