باستخدام Rails 3.1 ، أين تضع شفرة JavaScript الخاصة بـ "صفحة محددة"؟



14 Answers

بالنسبة إلى صفحة js الخاصة بالصفحة ، يمكنك استخدام حل Garber-Irish .

لذا قد يبدو مجلد Rails javascripts كهذا لجهازين للتحكم - السيارات والمستخدمين:

javascripts/
├── application.js
├── init.js
├── markup_based_js_execution
├── cars
│   ├── init .js
│   ├── index.js
│   └── ...
└── users
    └── ...

وسوف تبدو javascripts مثل هذا:

// application.js

//= 
//= require init.js
//= require_tree cars
//= require_tree users
// init.js

SITENAME = new Object();
SITENAME.cars = new Object;
SITENAME.users = new Object;

SITENAME.common.init = function (){
  // Your js code for all pages here
}
// cars/init.js

SITENAME.cars.init = function (){
  // Your js code for the cars controller here
}
// cars/index.js

SITENAME.cars.index = function (){
  // Your js code for the index method of the cars controller
}

و markup_based_js_execution سيحتوي على رمز للكائن UTIL ، وعلى تنفيذ UTIL.init جاهز DOM.

ولا تنسَ وضع هذا في ملف التخطيط الخاص بك:

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

وأعتقد أيضًا أنه من الأفضل استخدام الفصول بدلاً من سمات data-* ، للحصول على css الخاص بالصفحة الأفضل. كما ذكر Jason Garber: يمكن أن تكون محددات CSS الخاصة بالصفحات صعبة للغاية (عند استخدام سمات data-* )

آمل أن يكون هذا سيساعدك.

javascript ruby-on-rails ruby-on-rails-3.1 asset-pipeline sprockets

حسب فهمي ، يتم دمج جميع جافا سكريبت في ملف واحد. يفعل القضبان هذا افتراضيا عندما يضيف //= require_tree . إلى الجزء السفلي من ملف البيان application.js .

يبدو هذا وكأنه منقذ حقيقي للحياة ، ولكني أشعر ببعض القلق بشأن شفرة جافا سكريبت الخاصة بالصفحة. هل يتم تنفيذ هذا الكود في كل صفحة؟ آخر شيء أريده هو أن يتم إنشاء كل الأشياء الخاصة بي لكل صفحة عندما تكون مطلوبة فقط في صفحة واحدة.

أيضا ، أليس هناك احتمال للرمز الذي يصطدم أيضا؟

أو هل تضع علامة script صغيرة في أسفل الصفحة تستدعي فقط طريقة تقوم بتنفيذ شفرة جافا سكريبت للصفحة؟

هل لم تعد بحاجة إلى required.js بعد ذلك؟

شكر

تحرير : أنا أقدر كل الإجابات ... وأنا لا أعتقد أنهم حقا في الحصول على المشكلة. بعض منهم حول التصميم ولا يبدو أن تتصل ... والبعض الآخر مجرد ذكر javascript_include_tag ... التي أعلم أنها موجودة (من الواضح ...) ولكن يبدو أن الطريق Rails 3.1 المضي قدما هو اختتام جميع من JavaScript في ملف واحد بدلاً من تحميل جافا سكريبت الفردية في أسفل كل صفحة.

أفضل حل يمكن أن أقوم به هو التفاف بعض الميزات في علامات div ذات id s أو class es. في شفرة جافا سكريبت ، ما عليك سوى التحقق مما إذا كان الرقم id أو class موجودة في الصفحة ، وإذا كان الأمر كذلك ، فأنت تقوم بتشغيل شفرة جافا سكريبت المرتبطة بها. بهذه الطريقة إذا لم يكن العنصر الديناميكي موجودًا على الصفحة ، فلن يتم تشغيل شفرة جافا سكريبت - على الرغم من أنه تم تضمينه في ملف application.js الضخم الذي تم حزمه بواسطة Sprockets.

يستفيد الحل أعلاه من أنه إذا تم تضمين مربع بحث في 8 من 100 صفحة ، فسيتم تشغيله على 8 صفحات فقط. لن تحتاج أيضًا إلى تضمين نفس الرمز في 8 من صفحات الموقع. في الواقع ، لن تضطر أبدًا إلى تضمين علامات نصية يدوية على موقعك في أي مكان مرة أخرى.

أعتقد أن هذا هو الجواب الفعلي لسؤالي.




خيار آخر: لإنشاء ملفات خاصة بالصفحة أو النموذج ، يمكنك إنشاء أدلة داخل assets/javascripts/ المجلد الخاص بك.

assets/javascripts/global/
assets/javascripts/cupcakes
assets/javascripts/something_else_specific

يمكن تكوين ملف بيان application.js الرئيسي الخاص بك لتحميل ملفاته من global/ . يمكن أن تحتوي صفحات محددة أو مجموعات من الصفحات على ملفاتها الخاصة التي تقوم بتحميل الملفات من دلائلها الخاصة. تقوم أدوات Sprockets تلقائيًا بدمج الملفات التي تم تحميلها بواسطة application.js مع ملفات محددة للصفحة ، مما يسمح لهذا الحل بالعمل.

هذه التقنية يمكن استخدامها ل style_sheets/ كذلك.




أدرك أنني أتيت إلى هذا الحزب متأخراً بعض الشيء ، لكني أردت أن أضع حلاً كنت أستخدمه مؤخرًا. ومع ذلك ، اسمحوا لي أن أذكر أولا ...

القضبان 3.1 / 3.2 الطريق (لا يا سيدي. أنا لا أحب ذلك.)

انظر: http://guides.rubyonrails.org/asset_pipeline.html#how-to-use-the-asset-pipeline

أنا أذكر ما يلي من أجل اكتمال هذه الإجابة ، ولأنها ليست حلاً لا يطاق ... رغم أنني لا أهتم كثيراً به.

إن "Rails Way" هو حل موجه نحو التحكم ، بدلاً من كونه موجهًا للمقابلة كما طلب المؤلف الأصلي لهذا السؤال. هناك ملفات JS الخاصة بالتحكم المسمى بعد وحدات التحكم الخاصة بها. يتم وضع كل هذه الملفات في شجرة مجلد غير متضمنة افتراضيا في أي من application.js تتطلب توجيهات.

لتضمين التعليمات البرمجية الخاصة بالتحكم ، تتم إضافة ما يلي إلى طريقة العرض.

<%= javascript_include_tag params[:controller] %>

أنا أكره هذا الحل ، لكنه موجود وسريع. من المفترض أنه يمكنك بدلاً من ذلك تسمية هذه الملفات بشيء مثل "people-index.js" و "people-show.js" ثم استخدام شيء مثل "#{params[:controller]}-index" للحصول على حل موجه للرؤية. مرة أخرى ، حل سريع ، لكنه لا يتلاءم معي.

بلدي سمة البيانات الطريق

اتصل بي مجنونا ، ولكن أريد كل من JS بلدي تجميعها و minified في application.js عندما أقوم بنشر. لا أريد أن أتذكر أن أضع ملفات ستراغلر الصغيرة في كل مكان.

أقوم بتحميل كافة ملفات JS في ملف مضغوط واحد مؤقتًا سيتم تخزينه مؤقتًا. إذا كانت هناك حاجة إلى فصل جزء معين من التطبيق الخاص بي في الصفحة ، فأسمح لـ HTML أن تخبرني ، وليس Rails.

بدلاً من تأمين JS لمعرفات عناصر محددة أو تناثر HTML مع data-jstags العلامات ، أستخدم سمة بيانات مخصصة data-jstags باسم data-jstags .

<input name="search" data-jstag="auto-suggest hint" />

في كل صفحة ، أستخدم - أدخل طريقة مكتبة JS المفضلة هنا - لتشغيل التعليمات البرمجية عند انتهاء تحميل DOM. ينفّذ رمز bootstrapping هذا الإجراءات التالية:

  1. قم بالتكرار على جميع العناصر في DOM المميزة data-jstag
  2. بالنسبة إلى كل عنصر ، قسّم قيمة السمة في الفضاء ، وأنشئ صفيفًا من سلاسل العلامات.
  3. لكل سلسلة علامة ، قم بإجراء بحث في Hash لهذه العلامة.
  4. إذا تم العثور على مفتاح مطابق ، فقم بتشغيل الوظيفة المرتبطة به ، وتمرير العنصر كمعلمة.

لذلك ، قل أني قد حددت ما يلي في my application.js:

function my_autosuggest_init(element) {
  /* Add events to watch input and make suggestions... */
}

function my_hint_init(element) {
  /* Add events to show a hint on change/blur when blank... */
  /* Yes, I know HTML 5 can do this natively with attributes. */
}

var JSTags = {
  'auto-suggest': my_autosuggest_init,
  'hint': my_hint_init
};

سيقوم حدث bootstrapping بتطبيق my_autosuggest_init و my_hint_init مقابل مدخالت البحث ، ويحولها إلى مدخالت تعرض قائمة my_autosuggest_init بينما my_hint_init المستخدم ، فضالً عن توفير نوع من تلميحات اإلدخال عند ترك اإلدخال فارغًا وعدم تركيزه .

ما لم يتم وضع علامة على بعض العناصر باستخدام data-jstag="auto-suggest" ، data-jstag="auto-suggest" رمز الاقتراح التلقائي مطلقًا. ومع ذلك ، فهي دائمًا موجودة ومختزلة وأخيرًا في my app. js لتلك الأوقات التي أحتاج إليها على الصفحة.

إذا كنت بحاجة إلى تمرير معلمات إضافية إلى وظائف JS الموسومة ، فسيتعين عليك تطبيق بعض الإبداع. إما أن تضيف سمات paramet البيانات ، أو تخلق نوعًا من بناء جملة المعلمات ، أو حتى تستخدم نهجًا مختلطًا.

حتى إذا كان لدي بعض سير العمل المعقد الذي يبدو محددًا في وحدة التحكم ، فسأقوم فقط بإنشاء ملف له في مجلد lib الخاص بي ، وقم بتعبئته في application.js ، وقم بتمييزه بشيء مثل "new-thing-wizard". عندما يضرب بلدي bootstrap تلك العلامة ، سيتم إنشاء بلدي معالج ، يتوهم لطيفة وتشغيل. يتم تشغيله من أجل وجهة نظر وحدة التحكم هذه عند الحاجة ، ولكن لا يقترن بجهاز التحكم. في الواقع ، إذا قمت برمز المعالج الخاص بي إلى اليمين ، فقد أكون قادرًا على توفير جميع بيانات التهيئة في طرق العرض ، وبالتالي سيكون بمقدوري إعادة استخدام المعالج لاحقًا لأي وحدة تحكم أخرى تحتاج إليه.

على أي حال ، هذه هي الطريقة التي أقوم بها بتطبيق صفحة JS لفترة معينة الآن ، وقد خدمتني بشكل جيد لتصاميم الموقع البسيطة وللتطبيقات الأكثر تعقيدًا / غنى. نأمل أن يكون أحد الحلين اللذين عرضتهما هنا ، طريقتي أو طريق القضبان ، مفيدًا لأي شخص يأتي عبر هذا السؤال في المستقبل.




يمكنك إضافة هذا السطر في ملف التخطيط (على سبيل المثال ، application.html.erb) لتحميل ملف javascript الخاص بجهاز التحكم تلقائيًا (الذي تم إنشاؤه عند إنشاء وحدة التحكم):

<%= javascript_include_tag params[:controller] %>

يمكنك أيضًا إضافة سطر لتحميل ملف برنامج نصي تلقائيًا على أساس كل إجراء.

<%= javascript_include_tag params[:controller] + "/" + params[:action] %>

فقط ضع البرامج النصية لصفحتك في subdirectoriy مسماة بعد اسم وحدة التحكم. في هذه الملفات ، يمكنك تضمين برامج نصية أخرى باستخدام = تتطلب. سيكون من الجميل إنشاء مساعد لتضمين الملف فقط إذا كان موجودًا ، لتجنب فشل 404 في المتصفح.




ربما ستجد pluggable_js جوهرة كحل مناسب.




إجابة فيليب جيدة جدا. هنا هو رمز لجعلها تعمل:

في application.html.erb:

<body class="<%=params[:controller].parameterize%>">

بافتراض أن وحدة التحكم الخاصة بك تدعى المشاريع ، والتي سوف تولد:

<body class="projects">

ثم في projects.js.coffee:

jQuery ->
  if $('body.projects').length > 0  
     $('h1').click ->
       alert 'you clicked on an h1 in Projects'



هذه هي الطريقة التي حلت بها مشكلة التصميم: (عذر الهامل)

%div{:id => "#{params[:controller].parameterize} #{params[:view]}"}
    = yield

بهذه الطريقة أبدأ كل ملفات .css.sass الخاصة بالصفحة مع:

#post
  /* Controller specific code here */
  &#index
    /* View specific code here */
  &#new
  &#edit
  &#show

بهذه الطريقة يمكنك بسهولة تجنب أي اشتباكات. عندما يتعلق الأمر بملفات .js.coffee يمكنك فقط تهيئة عناصر مثل ؛

$('#post > #edit') ->
  $('form > h1').css('float', 'right')

آمل أن هذا ساعد البعض.




أوافق على إجابتك ، لمعرفة ما إذا كان هذا المحدد موجودًا ، استخدم:

if ($(selector).length) {
    // Put the function that does not need to be executed every page
}

(لم أر أي شخص يضيف الحل الفعلي)




I have another solution, which although primitive works fine for me and doesn't need any fancy selective loading strategies. Put in your nornal document ready function, but then test the current windows location to see if it is the page your javascript is intended for:

$(document).ready(function() {
   if(window.location.pathname.indexOf('/yourpage') != -1) {
          // the javascript you want to execute
   }
}

This still allows all the js to be loaded by rails 3.x in one small package, but does not generate much overhead or any conflicts with pages for which the js isn't intended.




Move all your commom JS files to a sub-folder like 'app/assets/javascript/global' then in the application.js, modify the //= require_tree . line to //= require_tree ./global .

Now you are free to put your controller-specific JS on the 'app/assets/javascript/' root and they will not be included in compiled JS, being used just when you call them via = javascript_include_tag on your controller/view.




Paloma project offers interesting approach to manage page specific javascript code.

Usage example from their docs:

var UsersController = Paloma.controller('Users');

// Executes when Rails User#new is executed.
UsersController.prototype.new = function(){
   alert('Hello Sexy User!' );
};



I haven't tried this out, but it looks like the following is true:

  • if you have a content_for that is javascript (eg with real javascript within it), sprockets would not know about it and thus this would work the same way as it does now.

  • if you want to exclude a file from the big bundle of javascript, you would go into config/sprockets.yml file and modify the source_files accordingly. Then, you would just include any of the files that you excluded where needed.




I combined some answers into:

Application helper:

module ApplicationHelper
  def js_page_specific_include
    page_specific_js = params[:controller] + '_' + params[:action]
    if Rails.application.assets.find_asset(page_specific_js).nil?
      javascript_include_tag 'application', 'data-turbolinks-track' => true
    else
      javascript_include_tag 'application', page_specific_js, 'data-turbolinks-track' => true
    end
  end
end

layouts/application.html.haml:

 <!DOCTYPE html>
%html{lang: 'uk'}
  %head   
    = stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true
   bla-bla-bla
    = js_page_specific_include   
   bla-bla-bla  



Here's how to do it especially if you don't have to execute tons of libraries for your specific page, but only to run a few hundreds lines of JS more or less.

نظرًا لأنه من الجيد تمامًا تضمين شفرة جافا سكريبت في HTML ، فكل ما عليك هو إنشاء دليل تطبيق / views shared.js ووضع صفحتك المحددة داخل الصفحات / الصفحات داخل my_cool_partial.html.erb

<script type="text/javascript"> 
<!--
  var your_code_goes_here = 0;
  function etc() {
     ...
  }
-->
</script>

والآن من أي مكان تريده ، ما عليك سوى القيام بما يلي:

  = render :partial => 'shared.js/my_cool_partial'

وهذا كل شيء ، ك؟




Related