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

我想使用一个简单的jQuery函数,如下所示:

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

从rails 5.1.3应用程序中的单个视图,在本例中为“login.html.erb”

在webpack的application.js我有:

 var $ = require('jquery'); 

这使得前面提到的jquery调用工作如果我将它放在相同的application.js文件上,但这意味着它将被调用所有页面,因为在布局上。

当我尝试在login.html.erb上运行它时,如下所示:

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

我在控制台上收到错误:“ReferenceError:$未定义”。

如果我尝试在login.html.erb文件中执行“从’jquery’;”导入$,我会收到此错误:“SyntaxError:import声明可能只出现在模块的顶层”,这可以理解为我的本地。 erb视图无法访问webpacker的application.js上引用的javascript,也无法从那里导入它。

我如何从视图中引用jquery以及webpacker所服务的任何模块?

如果以前曾经问过这个问题,我很抱歉,经过几天阅读关于webpack,webpacker gem和javascript而没有找到解决方案后,我发布了这个问题。

🙂

  1. 安装jQuery /bin/yarn add jquery
  2. 打开config/webpack/shared.js ,并使用以下代码添加/覆盖:

     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 slim

  3. 将jQuery global.$ = require('jquery')导入到app/javascripts/packs上的任何js文件中

现在你可以使用它了

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

首先要做的事情。 您无法使用webpacker在脚本标记内的erb模板中转换es6。

自从在rails中引入资产管道以来,一般的想法是提供多个javascript文件的捆绑。 在webpacker之前,通过定义链轮清单和现在的包 。 这允许保存js资产文件的http请求。 浏览器只会在第一个http请求中加载一个包含所有javascript的文件到应用程序并缓存它以进一步提供页面请求。

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

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

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

如果真的必须在主体上添加faded(不在模板中),你可以尝试通过“.login”类中的父匹配器选择它,或者以某种方式在rails布局中引入一个变量,该变量是在erb中设置的模板,以便为布局添加控制器特定标记。

如果您认为这不会产生很多http请求并且速度对您的用户来说足够好,那么每页还可以提供一个单独的js文件。 只需在pack文件夹中创建所有单独的packfiles即可。