簡體   English   中英

如何為 Ruby On Rails 編寫 JavaScript?

[英]How to write JavaScript for Ruby On Rails?

假設我有一個包含以下頁面的網站: Home About Friends

我想做的是創建一個簡單的 JavaScript 文件(稱為test.js ),所以當用戶按下按鈕時,我可以做一些簡單的事情,例如:

function myFunction(name) {
  console.log("Name = " + name);
}

現在到了我有問題的部分。 我注意到 ruby 使用project_name/app/views/layout/application.html.erb並為所有三個頁面( HomeAboutFriends )提供相同的<head>

但是,這不是我想在這里做的! 我只希望test.jsFriends頁面工作!

我是否在我的project_name/app/views/home/friends.html.erb中引用它,如下所示:

<!-- At the bottom of friends.html.erb -->
<script type="text/javascript" src="directory-to-javascript-file"></script>

我還注意到在這個目錄project_name/app/javascript下有一個 JavaScript 文件夾,其中包含兩個文件夾; channelspacks

這是我要添加test.js的地方,如果是,在哪個文件夾中?


所以總結一下:

  • 我必須將test.js文件保存在哪個文件夾中?
  • 在哪里引用test.js以便它只對Friends頁面可見?

您有 2 個選擇來放置 js、資產管道或 webpack。 資產管道可能更容易理解,在app/assets/javascripts/application.js中,您可以簡單地將測試 function 放在所有 require 語句之后(或將其提取到獨立文件並要求它)。 確保您的 application.html.erb 有一個<%= javascript_include_tag 'application'%>

您不需要在 friends.html.erb 中添加腳本標簽,將其刪除,讓布局和資產管道/webpacker 為您處理

第二種選擇是使用 webpacker。 有很多關於如何在 Rails 中使用它的資源,最終熟悉它可能會更好,我只是認為對於初學者來說,舊的資產管道可能更容易一些; webpack 過程非常相似,因此一旦您了解其中一個,您就可以輕松轉移到另一個。

在哪里引用 test.js 以便它只對好友頁面可見?

您可以為朋友 controller 創建一個新布局。

class FriendsController < ApplicationController
  layout "friends"
end

所以在你的布局目錄中創建一個friends.html.erb。 在friends.html.erb 中使用<%= javascript_include_tag 'friends' %> 接下來為朋友創建一個清單(或包)文件: app/assets/javascripts/friends.js並在其中需要您需要的任何內容。 這將意味着朋友 controller 將獲得自己的布局和自己獨立的 javascript。

我想這就是你要找的。

您提到您在app/javascript中有目錄pack ,似乎您正在使用 web 打包器用於 js 和 css。

所以這里是你的解決方案。

pack目錄中創建一個test.js

並將以下內容寫入您在問題中提到的project_name/app/views/home/friends.html.erb

<%= javascript_pack_tag 'test' %>

並在test.js文件中編寫所有 js 代碼。 這將被加載到僅提到的頁面中。

如果您想與其他區域(例如homeabout )進行相同的操作。 為此創建 js 文件並將<%= javascript_pack_tag 'js file name' %>包含到相應的 html.erb 文件中。

這將幫助您為每個模塊的視圖擁有相同的布局,但仍然擁有它自己的 uniq js,只需要特定的視圖。

您可能需要重新啟動 rails 服務器。

希望我的回答有幫助。

在 Rails 中,你真的想忘記“我只想在這個頁面上加載這個 JS 文件”的概念——我認為它是一種反模式,會讓你望而卻步。

Rails 使用資產管道/ webpacker來簡化您的 JS 交付,在舊版本中使用渦輪鏈接“ajaxify”常規頁面加載,Rails UJS 做了很多 ajax 詭計。 這意味着您很可能會處理 ajax 和持久的瀏覽器會話,這使得這個想法成為一個真正的問題,因為您的 JS 泄漏到您最初沒有想到的上下文中,或者除非您重新加載整個頁面否則根本無法工作.

而是考慮基於事件的編程和可以用來增強 UI 元素的行為。 想想“我想讓這種按鈕做 X”而不是“我想讓這個頁面上的這個特定的東西做 X”。 使用事件處理程序和 css 類來實現該目標:

document.addEventListener("click", (event) => { 
  if (!event.target.matches('.magic-button')) return;
  console.log('You clicked a magical button!');
});

這使您的 JS 與頁面本身分離並且可重用,並且實際上使您的初始問題沒有實際意義。 如果您不想在其他頁面上操作,請不要添加magic-button class。

如果你真的想做“每頁” Z action_name我用它來將controller_name名稱和動作名稱附加到正文元素的一種方法:

<body data-controller="<%= controller_name" %>" data-action="<%= action_name %>">

只需讀取數據屬性,您就可以知道自己在應用程序中的位置:

// given controller = foos and action = bar the events are:
// * MyApp:loaded
// * MyApp:foos#bar
// * MyApp:foos
// * MyApp:#bar
const firePageEvents = (event) => {
  // read the data attributes off the body element
  const body = document.querySelector('body');
  const details = {
    action: body.dataset.action,
    controller: body.dataset.controller
  };
  const eventNames = [
      "MyApp:loaded", 
      `MyApp:${controller}#${action}`, 
      `MyApp:${controller}`, 
      `MyApp:#${action}`
  ];
  // fire the events
  eventNames.forEach((name) => {
     let event = new CustomEvent(name, { detail: details });
     document.dispatch(event);
  });
}

// fires the events either when turbolinks replaces the page
// or when the DOM is ready
if (window.Turbolinks && Turbolinks.supported) {
  document.addEventListener("turbolinks:load", (event) => { 
    firePageEvents(event);
  });
} else {
  document.addEventListener("DOMContentLoaded", (event) => { 
    firePageEvents(event);
  });
}
// this will be trigged when any page is loaded
document.addEventListener("MyApp:loaded", (event) => {
  switch(event.details.action) {
    case 'about':
      console.log('about page loaded');
      break;
    case 'friends':
      console.log('friends page loaded');
      break;
  }
});

// this will be trigged when the an action named "about" is rendered:
document.addEventListener("MyApp:#about", (event) => {
  console.log('About page loaded', event.details);
});

// this will be triggered on the users load page
document.addEventListener("MyApp:users#index", (event) => {
  console.log('User#index page loaded', event.details);
});

然后我們觸發自定義事件,您可以附加事件偵聽器以使 JS 觸發特定的控制器/操作。

此代碼屬於您的資產管道/包中,其有效地連接和交付。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM