Ruby on rails 使用Rails 6,您将“;页面特定”;JavaScript代码?
我这里的问题与Rails 6相同,而不是Rails 3.1 假设我有一些JavaScript,我想用于我的帖子索引页面。我应该将该文件放在哪里,如何将其包括在内 在前面的问题中,答案通常使用Rails资产管道。然而,对于Rails6,我的理解是它使用webpacker而不是JavaScript文件的资产管道Ruby on rails 使用Rails 6,您将“;页面特定”;JavaScript代码?,ruby-on-rails,ruby-on-rails-6,webpacker,Ruby On Rails,Ruby On Rails 6,Webpacker,我这里的问题与Rails 6相同,而不是Rails 3.1 假设我有一些JavaScript,我想用于我的帖子索引页面。我应该将该文件放在哪里,如何将其包括在内 在前面的问题中,答案通常使用Rails资产管道。然而,对于Rails6,我的理解是它使用webpacker而不是JavaScript文件的资产管道 注意:我不希望总是包含该文件。如果我在作者索引页面上,我不希望包含帖子索引页面的JavaScript文件。为什么?假设我有$('li')。在('click',changeColor')在JS
注意:我不希望总是包含该文件。如果我在作者索引页面上,我不希望包含帖子索引页面的JavaScript文件。为什么?假设我有
$('li')。在('click',changeColor')代码>在JS文件中,用于posts索引页面。我可能不希望在authors索引页上运行该代码,但如果包含该文件,它会运行。您可以通过名称空间来解决这个问题,但我认为不包含不必要的文件会更干净(而且性能更高)。让我们在一个空的Rails 6应用程序中浏览一下这个目录的内容
▶ tree app/javascript
app/javascript
├── channels
│ ├── consumer.js
│ └── index.js
└── packs
└── application.js
2 directories, 3 files
packs目录对我们很重要,让我们看看它包含什么
//app/javascript/application.js
需要(“@rails/ujs”).start()
需要(“TurboLink”).start()
需要(“@rails/activestorage”).start()
要求(“渠道”)
webpack有一个入口点的概念,即它开始编译JavaScript代码时首先查找的文件
Webpacker gem以app/javascript/packs下的application.js文件的形式创建应用程序包。如果您还记得资产管道,那么这个文件相当于app/assets/javascripts/application.js文件
简单例子
如何将Javascript添加到RubyonRails(将Javascript添加为模块):
在Javascript路径app/Javascript
ex:'post'中创建文件夹
将javascript文件添加到index.js这样的文件夹中
在app/javascript/application.js
->require('post')
需要(“@rails/ujs”).start()
需要(“TurboLink”).start()
需要(“@rails/activestorage”).start()
要求(“渠道”)
要求(“职位”)
在添加post模块之后,让我们在Rails6应用程序中浏览一下该目录的内容
这是一种使用网页包的简单方法,与以前的rails风格相同。我将尝试用咖啡脚本回答您的问题
因为它更容易理解,
关键是使用事件“turbolinks:load”检查内容
如果rails使用新方法加载post页面,则默认情况下该页面将具有class.posts.new
在你的app.post.coffee中
class App.Post
render: ->
console.log "Post Edit / new render"
console.log "all this script below will only run"
console.log "if you open Post with new or edit method"
$(document).on "turbolinks:load", ->
if $(".posts.new")[0] || $(".posts.edit")[0]
post = new App.Post
post.render()
在你的app.author.coffee中
class App.Author
render: ->
console.log "Author Edit / newrender"
console.log "all this script below will only run"
console.log "if you open Author with new or edit method"
$(document).on "turbolinks:load", ->
if $(".authors.new")[0] || $(".authors.edit")[0]
author = new App.Author
author.render()
这里是post.js,如果我将我的咖啡脚本转换为js
App.Post = class Post {
render() {
console.log("Post Edit / new render");
console.log("all this script below will only run");
return console.log("if you open Post with new or edit method");
}
};
$(document).on("turbolinks:load", function() {
var post;
if ($(".posts.new")[0] || $(".posts.edit")[0]) {
post = new App.Post;
return post.render();
}
});
我将描述一些选项,以增加与Webpack和Webpack相关的体验的难度
忘记特定于页面的JavaScript,将所有内容都放在application.js
包中。这无疑是最容易理解的方法。对于一个小型应用程序来说,这种折衷可能是值得的,因为拥有一个更易于维护的应用程序可能会超过学习如何最好地将JS代码与Webpack分离的额外成本,而性能增益很小
用于延迟加载页面特定的代码。在这个场景中,您仍然会将所有JavaScript放在application.js
依赖关系图中,但并非所有代码都会预先加载。Webpack在编译您的JS时识别动态import()
函数,并将导入的区块分割成单独的文件,可使用JS框架路由器或简单触发器在浏览器中按需加载
例如,您可能有如下代码:
requireOnce('wysiwyg.js', function(){
$('textarea').wysiwyg()
});
if(document.queryselectoral(“.post index”).length){
导入(“./post/index”)//网页包将加载此JS异步
}
结合使用页面特定的“包”。在这种情况下,您不需要使用application.js
包,而是为每个需要区别对待的页面构建一个包,例如,posts.js
,admin.js
等。使用splitChunks插件意味着您的包可以正确地共享代码。我强烈建议您谨慎使用这种方法,直到您了解Webpack是如何工作的,或者在选择这条道路时愿意经历学习Webpack的过程。Webpack通常在假设每页只使用一个入口点的情况下工作得最好,否则,除非您知道自己在做什么,否则可能会在捆绑包中重复代码
以下是我如何使用TurboLink提供特定于页面的代码:
# javascript/packs/application.js
import {posts_show } from '../per_page/posts_show';
import {users_new } from '../per_page/users_new';
const pages = {posts_show, users_new};
document.addEventListener("turbolinks:load", () => {
# I am using gon to save the page name, but you can add page name to document body and then const page = document.body.className
const page = gon.controller_full
# check if method exist if true execute
if ('function' === typeof pages[page]){
new pages[page]
}
});
正如您所注意到的,我正在一个文件中编译所有的js,并根据需要执行它们
以下是一个后期展示的示例:
# javascript/per_page/posts_show.js
import {default as share_menu_init} from './methods/share_menu_init.js'
export class posts_show {
constructor() {
share_menu_init()
... # some other code here
}
}
您可以看到我正在导入share\u menu\u init
模块。如果我需要在页面之间共享一些方法,我会将它们存储在模块中,Webpack足够智能,不会创建重复的方法(如果我在posts\u show和其他页面中导入两次),它只会组织文件,以便我的posts\u show
可以访问此方法
const share_menu_init = () => {
... # some code here
}
export default share_menu_init
不确定这是否是提供页面特定代码的最佳方式,如果您有更好的方式,我想听听。您可以使用$。getScript
(函数(){
var requiredScripts=[];
window.requirence=函数(路径,cb){
if($.inArray(路径,requiredScripts)==-1){
requiredScripts.push(路径)
$.getScript(路径,cb)
}否则{
cb()
}
}
})();
像这样使用它:
requireOnce('wysiwyg.js', function(){
$('textarea').wysiwyg()
});
我忘了在问题中提到这一点(我会更新问题以包含它),但通过这种方法,app/javascript/post/index.js
似乎会一直包含在内,而我只希望在您位于特定页面时包含它。例如,我不希望在您访问a时将其包括在内