【问题标题】:What is the best way to organize unobtrusive JavaScript across multiple pages?跨多个页面组织不显眼的 JavaScript 的最佳方法是什么?
【发布时间】:2010-01-01 16:31:35
【问题描述】:

我喜欢 jQuery,但在使用更大的站点和多个页面时遇到了问题。我的问题是每个页面都有独特的要求,我需要知道告诉 jQuery 哪些页面激活某些东西的最佳方法。例如,有些表格需要Validator plug-in,有些不需要,有些表格使用DataTables plug-in,有些不需要,等等。

现在我想我可以在我的应用程序 JavaScript 文件中构建复杂的逻辑(switch 语句),根据它们所在的页面触发不同的操作,但这看起来很臭。这里的最佳实践是什么?

更新:关于这个问题有很多好主意,但不是我想要的。让我以更笼统的方式重新表述这个问题。

目前我正在使用 Rails 及其原型助手来构建我的 AJAX 组件,但我想转向 UJS。我如何告诉 jQuery 哪些链接/按钮要制作 AJAX 以及哪些要避免?而且,鉴于我可以区分应该具有 AJAX 的链接,我如何像使用助手一样为每个链接提供其自己的参数(方法、更新等)?

我的意思是除了针对每个单独的链接/按钮构建一个包含特定 jQuery 选择器的巨大页面之外。 :)

【问题讨论】:

    标签: javascript ruby-on-rails css-selectors


    【解决方案1】:

    jQuery 插件通常在 DOM 元素上激活,例如:

    $("#element").myPlugin();

    如果页面上不存在该元素,插件通常会通过不激活插件来安全地运行。

    如果您的插件不遵循这种结构,我建议您这样做:

    if($("#element").length) $("#element").myPlugin();
    

    【讨论】:

    • if 条件将始终评估为 true 作为具有属性 length 的对象,并且将返回值 0(以及其他属性)。因此,您应该检查长度属性 - if($("#element").length) { .... }
    • 是的,但是如果您有多个具有相同 DOM 元素的页面怎么办?例如,我的 validator() 插件设置为 $('form').validate(),但有时我不希望它作用于页面上的所有表单,只作用于其中的一些。在这种情况下我该怎么办?
    • @Richard: 给表单你想验证一个特殊的类?
    • @Christoph:是的,我就是这么想的。有时,您必须先从其他人那里得到一些东西,然后才能在您自己的脑海中变得有意义。 :)
    【解决方案2】:

    一个好的做法是在一个文件中包含所有页面所需的代码,并为需要特定功能的页面提供特定的 javascript 文件。听起来这就是你正在做的事情,所以我们有一个很好的基础。

    您可以通过多种方式构建哪些页面需要哪些文件,但请记住,在正常情况下,javascript 文件会被浏览器缓存,因此这些文件只需要下载一次。

    鉴于此评论

    是的,但是如果您有多个 具有相同 DOM 元素的页面?为了 例如,我的 validator() 插件已设置 像 $('form').validate() 一样,但是 有时我不想让它起作用 页面上的所有表格,只有一些 其中。在这种情况下我该怎么办?

    我建议提出一个约定,通过该约定来标记需要“附加”某些 jQuery 插件的页面中常见的元素。例如,如果您在需要validator() 插件的多个不同页面上有一个<form> 元素,但在任何一个特定页面上都有多个<form> 元素(并且并非所有<form> 元素都应该有validator() 插件),那么我建议使用 CSS 类来区分确实需要插件的 <form> 元素。

    <!-- HTML -->
    
    <!-- need to apply plugin to this -->    
    <form class="validator"> ... </form>
    
    <!-- but not to this -->
    <form> ... </form>
    
    <script type="text/javascript">
    // jQuery Code (in a separate file)
    
    $(function() {
        $('form.validator').validator();
    });
    </script>
    

    这样,插件将仅应用于与选择器匹配的&lt;form&gt; 元素。

    编辑:

    我不确定 rails 中的帮助程序是如何工作的,但是对于不直接属于 @987654332 的任何数据,您可以使用 bind() 方法的 data 参数将数据传递给 jQuery 中的事件处理程序@ 元素本身(如href 之类的属性)。如果某些链接需要 AJAX,那么使用 CSS 类标记这些链接并将 URL 存储在元素的 href 中可能是有意义的。然后在您的 jQuery 代码中,可以在任何具有通过 AJAX 发出请求的链接的页面上使用,您可以执行类似的操作

    <a class="ajax-link" href="/get/someData.php">Data retrieved through AJAX</a>
    
    <a href="/normalLink.php">Standard link with no AJAX</a>
    
    <script type="text/javascript">
    $('a.ajax-link').bind('click',ajaxRequest);
    
    function ajaxRequest(e) {
        e.preventDefault(); 
        $.get(e.target.href, function(data) {
          $('#loadDiv').html(data);
        });
    }
    </script>
    

    当用户禁用 JavaScript 时,该链接将按照正常链接工作,但在启用 JavaScript 时将发出 AJAX 数据请求。我在这里使用了一个命名函数,ajaxRequest,因为它可以更容易地调试脚本(也许还可以重用),但如果你愿意,你可以使用匿名函数。

    【讨论】:

    • 出色的洞察力。在我的例子中,有一个特定的(非常大的)表单不需要 validator() 插件,所以我可能会使用“NOT”选择器来排除它。类似 $('form:not(.no-validate)').validate(); ...
    • 当然,如果您需要将插件应用于除一个 &lt;form&gt; 元素之外的所有元素,那么使用 :not 选择器可能比将 CSS 类应用于确实需要插件的所有元素更好.仅获取所有 &lt;form&gt; 元素然后使用 filter() 删除不需要的元素可能会稍微快一些,而不是使用复杂的选择器字符串。
    【解决方案3】:
    【解决方案4】:

    我经常做的一件事是在每个页面的body 标记中添加一个id,其中id 是页面的名称(&lt;body id="contact"&gt;)。这使得 javascript 和 css 选择都非常容易。

    例如:

    <!-- HTML -->
    
    <!-- need to apply plugin to these forms -->    
    <form> ... </form> on the about.php page
    
    <!-- but not to this -->
    <form> ... </form> on the index.php page
    
    <script type="text/javascript">
    // jQuery Code (in a separate file)
    
    $(function() {
        $('body#about form').validator();
    });
    </script>

    【讨论】:

    • 这是在不同页面上执行不同操作的好方法。但是,我正在使用 Rails,但我认为它不会像这样工作。我可以为每种类型的页面构建一个单独的布局文件,但这不会很干,并且会使缓存标题更加困难。
    【解决方案5】:

    您可以将键值对传递给您的主要 JavaScript 模块,以告知应该导入哪些插件。 This technique is used by scriptaculous.

    <script type="text/javascript" src="scriptaculous.js?load=effects,dragdrop">
    

    另一种方法是在服务器端定义每个表单/页面需要哪些媒体文件,以便可以自动呈现 html,并带有指向将要使用的脚本的链接。 Django has a good implementation of this technique:

    class CalendarWidget(forms.TextInput):
        class Media:
            css = {
                'all': ('pretty.css',)
            }
            js = ('animations.js', 'actions.js')
    

    【讨论】:

    • 这是一个非常酷的技术,但我在 Rails 上,据我所知它没有这样的东西。
    猜你喜欢
    • 1970-01-01
    • 2011-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-06
    • 1970-01-01
    相关资源
    最近更新 更多