【问题标题】:Why are my js.erb views not working when using webpacker in Rails 6 with bootstrap?为什么在带有引导程序的 Rails 6 中使用 webpacker 时我的 js.erb 视图不起作用?
【发布时间】:2020-05-19 17:44:18
【问题描述】:

我正在尝试将一些简单的 Ajax 添加到我的 Rails 应用程序中。我正在使用带有 webpack 的 Bootstrap。 我的webpack/environment.js 文件看起来像这样

const { environment } = require('@rails/webpacker')

const webpack = require('webpack')
environment.plugins.append('Provide',
  new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery',
    Popper: ['popper.js', 'default']
  })
)

module.exports = environment

我的javascript/packs/application.js 看起来像这样

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")
import 'bootstrap'
import 'src/main'
import 'style/main'

我正在尝试为 create.js.erb 中的一个模型添加一些 Ajax

$("#question-<%= @exam_option.exam_question.id %>-options").append("<%= escape_javascript render 'exam_option', option: @exam_option %>");
$('#add_option_modal').modal('hide');

当我尝试添加我的选项之一时,我收到控制台错误

ReferenceError: Can't find variable: $

我一直在寻找解决方案,但没有成功。

我做错了什么?谢谢!

编辑:

当我将 Bootstrap 添加到我的应用程序时,我遵循了这个 guide 。遵循指南时,我使用 yarn 安装了 bootstrap、jquery 和 popper.js

yarn add bootstrap jquery popper.js

Bootstrap 使用的 jQuery 工作正常(例如工具提示)。 根据@mechnicov 的回答,我尝试将environment.js 更改为

const webpack = require('webpack')
environment.plugins.append('Provide',
  new webpack.ProvidePlugin({
    $: 'jquery/src/jquery',
    jQuery: 'jquery/src/jquery',
    Popper: ['popper.js', 'default']
  })
)

我在 import 'bootstrap' 上方添加了require("jquery") application.js

当我进行这些更改时,create.js.erb 中的代码可以正常工作,但它会使我的 Bootstrap 无法正常运行并引发诸如TypeError: ... $('[data-toggle="tooltip"]').tooltip() undefined 之类的错误。

编辑 2

根据接受的答案,我将application.js 更改为:

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")
window.jQuery = window.$ = require('jquery')
import 'bootstrap'
import 'src/main'
import 'style/main'

似乎一切正常,但我不确定为什么需要以这种方式添加它? Webpack 不应该从我的environment.js 文件中执行此操作吗? 如果有人可以解释这一点,请这样做。

【问题讨论】:

  • 遇到了类似的问题(下面的答案没有帮助):你把 create.js.erb 放在哪里?在 /app/javascript/pack --or-- /app/views/blabla ?我需要包含一个 javascript_pack_tag 吗?谢谢
  • 通常在您正在使用的模型/控制器的视图文件夹中。您也可以通过执行类似'format.js { render'folder_name/create.js.erb}'之类的操作在不同的目录中调用它,并将“folder_name”替换为它所在的视图目录。希望有所帮助。

标签: javascript ruby-on-rails webpack


【解决方案1】:

你能试试下面的代码吗:-

# javascript/packs/application.js

window.jQuery = window.$ = require('jquery')

# javascript/packs/application.js

require("jquery")
window.jQuery = $;
window.$ = $;

我也遇到了同样的问题,但是上面的代码当时对我有用

希望这对您也有帮助。 :)

【讨论】:

  • 感谢您的回答。我应该把这段代码放在哪里?
  • 我刚刚编辑了我的答案..你可以重新检查... :)
  • 你拯救了我的一天
【解决方案2】:

似乎一切正常,但我不确定为什么需要添加它 这边走? Webpack 不应该从我的 environment.js 中执行此操作 文件?如果有人可以解释这一点,请这样做。

我将根据您在问题中所做的编辑来回答您的问题,您需要了解的是 webpack 的工作原理,基本上您有:

1 - 一个入口文件,它是您的源代码文件(包含“导入”和/或其他 javascript 代码)

2 - Webpack 获取该入口文件,将其打包,然后生成一个输出文件。在您的应用程序中,这就是您最终使用的内容,即最终输出/捆绑包。

在 Rails 中,Webpacker 是开箱即用地为您配置 webpack 并隐藏无聊细节的 gem,因此您可以直接开始使用它。

在 webpacker 中,你放在javascript/packs 中的任何文件都被视为入口文件,默认情况下我们有application.js,所以app/javascript/packs/application.js 是你的入口文件,输出文件将具有相同的名称并附加一个哈希字符串,例如 application-ff14101dff18182f89f6.js

假设您向 app/javascript/packs 添加了另一个名为 admin.js 的文件(这是另一个入口文件),将会发生的情况是 Webpacker 被配置为从每个入口文件生成一个输出文件。这意味着编译后,您将有另一个文件admin-ff14101dff18182f89f6.js 作为输出。

输出文件放在 Rails 应用程序中的/packs/js 下,您可以从布局中调用它们,如下所示:

<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'admin', 'data-turbolinks-track': 'reload' %

您甚至可以在 layouts/application.html.erb 中使用第一个标签,在另一个布局中使用第二个标签,例如,layouts/admin.html.erb,您不必将所有代码推送到一个巨大的 application.js 中(是的,您可以只加载必要的脚本,让您的网站更快)。

现在你已经了解了基础知识,是时候回答你的问题了,正如我们之前所说的,Webpacker 使用 app/javascript/packs 中的任何 JS 文件作为入口文件,您可以通过打开 config.webpacker.yml 文件来验证这一点,并找到以下内容:

default: &default
  source_path: app/javascript
  source_entry_path: packs // <------ The location of the entry files
  public_root_path: public
  public_output_path: packs // <------ The location of the output/bundle
  ...

因此,即使您通过 ProvidePlugin 在 environment.js 中公开 jQuery,它也只能用于 webpack 配置的源路径,即 app/javascript。这就解释了为什么您无法从 app/views/some-view-folder/create.js.erb 访问 jquery。

你可能会问,可以以某种方式将视图文件夹app/views/some-view-folder 暴露给 webpack 吗?理论上是的,通过“解析”webpacker 为其配置的文件夹(参见 config/webpacker.yml):

# Additional paths webpack should lookup modules
# ['app/assets', 'engine/foo/app/assets']
resolved_paths: []

可以执行resolved_paths: ['app/views/some-view-folder'] 之类的操作,这意味着如果您在 application.js 中导入 create.js.erb,webpack 将能够找到该文件并将其导入,但实际上它没有任何意义作为 create .js.erb 需要在运行时执行并从您的应用程序执行其他 ruby​​ 代码,它用于动态呈现视图,而不是像 JS 文件那样用于静态目的(对不起,我对 Rails 内部了解不多,但你明白了)

通过window.jQuery = window.$ = $,您将 jQuery 暴露给 window 对象,这使其成为全局对象,但您始终可以在app/javascript 下的文件中使用常规 ajax 请求,而不是依赖于 remote: true 之类的东西,具体取决于是否要全局公开。

我希望这对你有所帮助,我为初学者写了一本关于 webpack 的书,如果你感兴趣,你可以在 amazonapress 上查看,这将使你全面了解 webpack 的工作原理,无论你是使用 Rails 或任何其他框架:)

【讨论】:

    【解决方案3】:

    你没有加载 JQuery。

    将其添加到您的节点模块中:

    $ yarn add jquery
    

    config/webpack/environment.js中写入JQuery的正确路径

    const { environment } = require('@rails/webpacker')
    
    const webpack = require('webpack')
    environment.plugins.prepend('Provide',
      new webpack.ProvidePlugin({
        $: 'jquery/src/jquery',
        jQuery: 'jquery/src/jquery',
        Popper: ['popper.js', 'default']
      })
    )
    
    module.exports = environment
    

    javascript/packs/application.js中的引导之前添加一行:

    require("jquery")
    

    不要忘记主布局视图中的javascript_pack_tag 'application'

    希望这会对你有所帮助。

    【讨论】:

    • 感谢您的回答,我编辑了我的问题以提供更多信息。
    猜你喜欢
    • 2020-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-16
    • 2022-01-06
    • 2021-01-12
    相关资源
    最近更新 更多