Rail 6 Webpack import JS third party library Uncaught ReferenceError: x is not defined
Rail 6 Webpack import JS third party library Uncaught ReferenceError: x is not defined
我想在我的 Rails 应用程序中使用 ToastifyJS 作为 toast 的 JS 库。由于 Rails 6 默认使用 Webpack,所以我做了 google 一段时间,但最终没有结果。
这是我所做的:
安装Rails6:
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();
})
按预期工作。但是我想要的有点不同。作为 toast/notification,您可以编写如下代码:
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
我在我的社区问过这个问题,所以我会在这里总结一下答案。这不是 Rails 或 Rails 6 的问题。问题是关于 scope。我们需要将我们的库公开到全球范围。
我们可以通过window对象手动暴露或者使用WebpackProvidePlugin
.
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 编译,所以它不会被定义。
所以我们可以:
- 使用 window 对象公开:
window.myModule = myModule
- Using Webpack
expose-loader
(其实就是暴露使用window对象)
但是我们不应该在全局范围内编写脚本或动态插入脚本标签。在这种特定情况下,渲染吐司。我们应该:
- 吐司时输出html
data-
属性
- 在
app/packs/application.js
导入js库
- 使用
getElementByClass
...然后获取有关toasts的数据
- 在这些 toasts 上执行库代码
我们应该将信息嵌入到 DOM 中,因为:
- 无需在视图模板中编写js
- 可以
defer
脚本执行
- 渐进增强
我想在我的 Rails 应用程序中使用 ToastifyJS 作为 toast 的 JS 库。由于 Rails 6 默认使用 Webpack,所以我做了 google 一段时间,但最终没有结果。
这是我所做的:
安装Rails6:
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();
})
按预期工作。但是我想要的有点不同。作为 toast/notification,您可以编写如下代码:
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
我在我的社区问过这个问题,所以我会在这里总结一下答案。这不是 Rails 或 Rails 6 的问题。问题是关于 scope。我们需要将我们的库公开到全球范围。
我们可以通过window对象手动暴露或者使用WebpackProvidePlugin
.
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 编译,所以它不会被定义。
所以我们可以:
- 使用 window 对象公开:
window.myModule = myModule
- Using Webpack
expose-loader
(其实就是暴露使用window对象)
但是我们不应该在全局范围内编写脚本或动态插入脚本标签。在这种特定情况下,渲染吐司。我们应该:
- 吐司时输出html
data-
属性 - 在
app/packs/application.js
导入js库 - 使用
getElementByClass
...然后获取有关toasts的数据 - 在这些 toasts 上执行库代码
我们应该将信息嵌入到 DOM 中,因为:
- 无需在视图模板中编写js
- 可以
defer
脚本执行 - 渐进增强