【问题标题】:Rail 6 Webpack import JS third party library Uncaught ReferenceError: x is not definedRail 6 Webpack 导入 JS 第三方库 Uncaught ReferenceError: x is not defined
【发布时间】:2019-07-14 06:14:45
【问题描述】:

我想在我的 Rails 应用程序中使用 ToastifyJS 作为 Toast 的 JS 库。由于 Rails 6 使用 Webpack 作为默认设置,所以我在谷歌上搜索了一段时间,结果一无所获。

这是我所做的:

安装 Rails 6:

rails _6.0.0.rc1_ new myapp -d mysql

安装 JS 库 toastify-js:

yarn add toastify-js

app/assets/stylesheets/application.scss

@import "toastify-js/src/toastify";

app/javascript/packs/application.js

import Toastify from 'toastify-js'

document.addEventListener("turbolinks:load", () => {
  Toastify({
    text: "This is a toast",
    duration: 3000,
    destination: "https://github.com/apvarun/toastify-js",
    newWindow: true,
    close: true,
    gravity: "top", // `top` or `bottom`
    position: 'left', // `left`, `center` or `right`
    backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
    stopOnFocus: true // Prevents dismissing of toast on hover
  }).showToast();
})

按预期工作。但是我想要的有点不同。作为祝酒词/通知,您可以编写如下代码:

app/views/layouts/application.html.erb

<% if flash.any? %>
  <script type="text/javascript">
    document.addEventListener("turbolinks:load", () => {
      <% flash.each do |key, value| %>
        Toastify({
          text: "<%= value %>",
          backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)"        
        }).showToast();
      <% end%>
    })
  </script>
<% end %>

我收到了这个错误:Uncaught ReferenceError: Toastify is not defined 虽然我在application.js 中做了import Toastify from 'toastify-js'?

还有一件事,为了让代码结构更简洁,我把所有关于toast的js都写在一个文件里了:

app/javascript/packs/toast.js

import Toastify from 'toastify-js'

const toastNotice = Toastify({
  text: "This is a toast",
  backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
});

const toastAlert = Toastify({
  text: "This is a toast",
  backgroundColor: "linear-gradient(to right, #fcb045, #fd1d1d)",
});

app/javascript/packs/application.js

import './toast.js'

app/views/shared/_flash.html.erb

<% if flash.any? %>
  <script type="text/javascript">
    <% flash.each do |key, value| %>
      toast<%= key.capitalize %>.options.text = "<%= value%>";
      toast<%= key.capitalize %>.showToast();
    <% end%>
  </script>
<% end %>

但我又收到了Uncaught ReferenceError: toastAlert is not defined

【问题讨论】:

    标签: javascript ruby-on-rails webpack webpacker


    【解决方案1】:

    我在我的社区提出了这个问题,所以我将在这里总结答案。这不是 Rails 或 Rails 6 的问题。问题在于 范围。我们需要将我们的库暴露给全局范围。

    我们既可以通过 window 对象手动暴露,也可以使用 Webpack ProvidePlugin.

    罢工>

    const { environment } = require('@rails/webpacker')
    
    environment.plugins.prepend('Provide',
        new webpack.ProvidePlugin({
            Toastify: 'toastify-js/src/toastify'
        })
    )
    
    module.exports = environment
    

    但是,使用 ProvidePlugin 不会将库公开到全局范围。它仅在我们使用 Webpack 编译到库的地方可用,这意味着在 app/packs/application.js 内部。所以当我们在视图模板中编写脚本时,那些代码并没有被 Webpack 编译,所以不会被定义。

    所以我们可以:

    1. 使用窗口对象公开:window.myModule = myModule
    2. 使用Webpack expose-loader(其实就是用window对象暴露)

    但是我们不应该在全局范围内编写脚本或动态插入脚本标签。在这种特定情况下,渲染 toast。我们应该:

    1. 当我们有 toast 时输出 html data- 属性。
    2. 在app/packs/application.js导入js库
    3. 使用 getElementByClass ...然后获取有关 toast 的数据
    4. 在这些 toast 上执行库代码

    我们应该将信息嵌入到 DOM 中,因为:

    1. 视图模板不用写js
    2. 可以defer脚本执行
    3. 渐进式增强

    【讨论】:

      猜你喜欢
      • 2020-05-10
      • 1970-01-01
      • 1970-01-01
      • 2018-08-03
      • 1970-01-01
      • 2020-11-18
      • 2020-10-13
      • 2020-03-25
      • 2018-05-13
      相关资源
      最近更新 更多