Rail 6 Webpack导入JS第三方库未捕获ReferenceError:x未定义

时间:2019-07-14 06:14:45

标签: javascript ruby-on-rails webpack webpacker

我想在我的Rails应用程序中将ToastifyJS用作JS Toast的JS库。由于Rails 6使用Webpack作为默认设置,因此我做了一段时间的Google搜索,结果没有了。

这是我所做的:

安装Rails 6:

WITH 
  running_purchase AS
  ( SELECT transaction_id, created_at, quantity, item_id, price,
           SUM(quantity) OVER (PARTITION BY item_id
                               ORDER BY created_at, transaction_id
                               ROWS BETWEEN UNBOUNDED PRECEDING
                                        AND CURRENT ROW)
             AS running_total
    FROM article_receives
  ),
  running_stock AS
  ( SELECT demand_id, created_at, quantity, item_id, 
           SUM(quantity) OVER (PARTITION BY item_id
                               ORDER BY created_at, demand_id
                               ROWS BETWEEN UNBOUNDED PRECEDING
                                        AND CURRENT ROW)
             AS running_total
    FROM article_issues
  )
SELECT 
    s.demand_id, p.transaction_id,p.created_at as purchase_date, p.item_id, p.price, s.created_at as issue_date,
    LEAST(p.running_total, s.running_total) 
    - GREATEST(s.running_total - s.quantity, p.running_total - p.quantity)
        AS quantity
FROM running_purchase AS p
  JOIN running_stock AS s
    ON  p.item_id = s.item_id
    AND s.running_total - s.quantity < p.running_total  
    AND p.running_total - p.quantity < s.running_total 
WHERE s.created_at BETWEEN '2019-06-01' AND DATE_ADD('2019-06-30', INTERVAL 1 DAY)
ORDER BY
    p.item_id, p.created_at, p.transaction_id ;

安装JS库toastify-js:

rails _6.0.0.rc1_ new myapp -d mysql

app / assets / stylesheets / application.scss

yarn add toastify-js

app / javascript / packs / application.js

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

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

app / views / layouts / application.html.erb

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();
})

我收到以下错误消息:<% 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中做了import Toastify from 'toastify-js'吗?

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

app / javascript / packs / toast.js

application.js

app / javascript / packs / application.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 / views / shared / _flash.html.erb

import './toast.js'

但是我又得到了<% 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 %>

1 个答案:

答案 0 :(得分:0)

我在社区中问了这个问题,所以我将在这里总结答案。这不是Rails或Rails 6的问题。问题与 scope 有关。我们需要将我们的库暴露给全球范围。

我们可以通过窗口对象手动公开,也可以使用 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. 公开
  3. 使用Webpack expose-loader(实际上它的作用是使用窗口对象公开)

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

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

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

  1. 无需在视图模板中编写js
  2. 可以defer执行脚本
  3. 渐进增强