简体   繁体   English

Rails内联Javascript和最佳实践

[英]Rails inline Javascript and Best Practices

I'm kinda new to using Rails, and an app I am working on is progressing well - however I'm looking though the generated HTML and noticed things like... 我对使用Rails 有点新手,我正在开发的应用程序进展顺利 - 不过我正在查看生成的HTML并注意到......

<script type="text/javascript">
//<![CDATA[
Droppables.add(...);
//]]>
</script>

Sprinkled around the HTML, which of course matches up with places where I use: 洒在HTML周围,当然与我使用的地方相匹配:

<%= drop_receiving_element ... %>

What I'm wondering is... is there a better way to do this, or make it cleaner? 我想知道的是......有更好的方法来做到这一点,还是让它更干净? Some of these script tags are coming from partials so putting them at the 'bottom of the page' doesn't really help in this situation. 其中一些脚本标签来自部分标签,因此将它们放在“页面底部”并不能真正帮助解决这种情况。

Another option may be pushing all these 'tag blocks' into an array then writing them out in the application.rhtml file, but its still a bit messy... 另一种选择可能是将所有这些“标记块”推入一个数组,然后将它们写在application.rhtml文件中,但它仍然有点凌乱......

Well if you really want to use best practices...Do not use inline javascript. 好吧,如果你真的想要使用最佳实践...不要使用内联JavaScript。 Keep your HTML, CSS and Javascript clean and seperated from eachother. 保持您的HTML,CSS和Javascript清洁并彼此分离。 Ideally the html file should be usable without CSS and javascript. 理想情况下,html文件应该可以在没有CSS和javascript的情况下使用。

The cleanest way, imo, is to just build your app using plain html/css, and enhance it with unobtrusive javascript to provide a better user experience. 最简洁的方法是使用普通的html / css构建你的应用程序,并使用不引人注目的javascript来增强它,以提供更好的用户体验。

A pattern for this is to include all your JS files at the bottom of your page, and start running your code with functionality like onDomReady. 这种模式是将所有JS文件包含在页面底部,并开始使用onDomReady等功能运行代码。

Based on the comments I would like to add some possible options to get you started: 根据评论,我想添加一些可能的选项来帮助您入门:

  • JQuery JQuery的
  • YUI YUI
  • Prototype 原型

Best practice is to remove all inline javascript. 最佳做法是删除所有内联JavaScript。 However, there are 3 cases that I've run into where you absolutely need inline javascript: 但是,有3个案例我遇到了你绝对需要内联javascript的问题:

1. To resolve image errors 1.解决图像错误

If an image tag is referencing an image path that doesn't exist, the only way to prevent the image error from appearing (even in the web inspector) is to do this: 如果图像标记引用了不存在的图像路径,则防止图像错误出现的唯一方法(即使在Web检查器中)是这样做的:

<img src="/i/dont/exist.png" onerror="$(this).attr("src", "/i/do/exist.png")" />

The following doesn't work because the onerror event is executed before you even have time to grab the image with jQuery: 以下不起作用,因为在您有时间使用jQuery获取图像之前执行onerror事件:

$("img").error(function() {
  $(this).attr("src", "/i/do/exist.png")
});

The code below doesn't work either because the onerror event doesn't bubble: 下面的代码不起作用,因为onerror事件不会冒泡:

$("img").live("error", function() {
  $(this).attr("src", "/i/do/exist.png");
});

So you have to use inline javascript for that. 所以你必须使用内联javascript。

2. To render javascript templates as the page loads 2.在页面加载时呈现javascript模板

If you wait until $(document).ready to draw your feed of content into one of the empty container elements in your dom, the user will see the blank spot for a split second. 如果你等到$(document).ready将你的$(document).ready绘制到你的dom中的一个空容器元素中,用户将看到一瞬间的空白点。 This is why when your Twitter page first loads, the feed is blank for an instant. 这就是为什么当您的Twitter页面首次加载时,Feed暂时为空白。 Even if you just put an external script file at the bottom of the dom, and in there you append the dynamically generated html elements to your page without even using $(document).ready , it's still too late. 即使您只是将一个外部脚本文件放在dom的底部,并且在那里您将动态生成的html元素追加到您的页面而不使用$(document).ready ,它仍然为时已晚。 You have to append the dynamic nodes immediately after the container element is added: 您必须在添加容器元素后立即附加动态节点:

<script>App.bootstrap({some: "json"});</script>
<nav id='navigation'></nav>
<header id='header'></header>
<section id='content'>
  // dynamic content here
</section>
<script>App.renderContent();</script>
<aside id='sidebar'>
  // dynamically toggle which one is selected with javascript
  <nav>
    <h3>Search By Category</h3>
    <ol>
      <li>
        <a href="/category-a">Category A</a>
      </li>
      <li>
        <a href="/category-b">Category B</a>
      </li>
    </ol>
  </nav>
</aside>
<script>App.renderSidebar();</script>
<footer id='footer'></footer>

3. You're bootstrapping your app with JSON 3.你用JSON引导你的应用程序

If you're using JSON + javascript templates, it's a good idea to bootstrap the first set of data into the response body by including it inline in the page (in the above dom example too). 如果您正在使用JSON + javascript模板,最好通过将第一组数据内联到页面中来引导第一组数据(在上面的dom示例中)。 That makes it so you don't need an additional ajax request to render content. 这使得您不需要额外的ajax请求来呈现内容。

Everything else should be done with Unobtrusive Javascript 其他一切都应该使用Unobtrusive Javascript完成

Rails has a lot of javascript helpers, and thankfully in Rails 3 most (all?) of it is unobtrusive; Rails有很多javascript助手,幸好在Rails 3中,大多数(全部?)都是不引人注目的; they're now using the data- attribute and an external rails.js file. 他们现在正在使用data-属性和外部rails.js文件。 However, many of the gems out there that are part-ruby part-javascript tend to still write helper methods add complex javascript inline: 然而,许多部分红宝石部分javascript的宝石倾向于仍然编写辅助方法添加复杂的javascript内联:

That's helpful, but I think just having a clear README describing how to add the javascript to your application.js is even more useful. 这很有帮助,但我认为只有一个清晰的自述文件描述如何将javascript添加到您的application.js更有用。 External javascript makes it a lot easier to customize/extend the functionality down the road, it gives you a lot more control over the system, and it minimizes duplication across your html pages (so the response body is smaller, and the browser can cache external javascript files). 外部javascript使得更容易定制/扩展功能,它可以让您更好地控制系统,并最大限度地减少html页面的重复(因此响应体更小,浏览器可以缓存外部javascript文件)。 Unless you need to handle missing images, instantaneous rendering, or bootstrap some json, you can put everything else in external javascript files and never have to use Rails javascript/ajax helpers. 除非您需要处理丢失的图像,即时渲染或引导某些json,否则您可以将其他所有内容放在外部javascript文件中,而不必使用Rails javascript / ajax帮助程序。

Sometimes inline JavaScript is useful for critical, fast views (eg, certain landing pages), or small snippets (eg, Facebook SDK initialization, Analytics/Kissmetrics initialization scripts, etc.) where using no external libraries can speed up page load. 有时,内联JavaScript对于关键的快速视图(例如,某些登录页面)或小型片段(例如,Facebook SDK初始化,Analytics / Kissmetrics初始化脚本等)非常有用,其中不使用外部库可以加速页面加载。 For those cases, I recommend using a partial _facebook.js.erb inside layouts, and define a helper: 对于这些情况,我建议在布局中使用部分_facebook.js.erb,并定义一个帮助器:

module ApplicationHelper
  def facebook_tag
    content_tag :script, render(partial: 'layouts/facebook.js')
  end
end

Then, create the file _facebook.js.erb and include the inline JavaScript inside application.html.erb using the defined helper: 然后,创建文件_facebook.js.erb并使用定义的帮助程序在application.html.erb中包含内联JavaScript:

<%= facebook_tag %>

For any other case, such as the partials you mention that inline JavaScript, I recommend using unobtrusive JavaScript as other answers suggest. 对于任何其他情况,例如您提到内联JavaScript的部分内容,我建议使用不引人注目的JavaScript,如其他答案所示。

This bothered me for a while and I eventually came up with a two pronged approach. 这困扰了我一段时间,我最终想出了一个双管齐下的方法。

If you are developing a web application for a closed domain, where search engine performance and javascript are not an issue, just be pragmatic and let Rails' javascript helpers do their thing. 如果您正在为封闭域开发Web应用程序,其中搜索引擎性能和JavaScript不是问题,那么只需务实并让Rails的javascript助手做他们的事情。

If you are developing for the web at large then do what Tomh sugested and code in plain html/css and then enhance onDomReady. 如果你正在为网络开发,那么做Tomh sugested并用普通的html / css编码,然后增强onDomReady。

If you still want to use Rails helpers like button_to_remote that use inline javascript, then code your page load handler to send an Ajax request to the server. 如果你仍然想使用像使用内联javascript的button_to_remote这样的Rails助手,那么编写你的页面加载处理程序来向服务器发送Ajax请求。 you can then use page.replace / page.replace_html to replace your regular page elements with code returned from the helpers. 然后,您可以使用page.replace / page.replace_html将常规页面元素替换为从帮助程序返回的代码。

I'd also recommend going with the unobtrusive Javascript approach and use jQuery . 我还建议使用不引人注目的Javascript方法并使用jQuery

For a great introductory tutorial on how to do that with Rails take a look at this jQuery + Rails screencast by Ryan Bates . 有关如何使用Rails执行此操作的精彩入门教程,请查看Ryan Bates的这个jQuery + Rails截屏视频

If you'd like to keep using helpers with jQuery, then take a look at a jRails , but if you do that, you'll still be violating the unobtrusive Javascript premise. 如果你想继续使用jQuery的帮助器,那么看看jRails ,但是如果你这样做,你仍然会违反不引人注目的Javascript前提。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM