【问题标题】:Best practice for using JavaScript in Django在 Django 中使用 JavaScript 的最佳实践
【发布时间】:2025-12-19 01:20:13
【问题描述】:

我想用一些 JavaScript/jQuery 推送我的 Django 项目。为了从一开始就做好,我想知道,哪种组织 .js 文件的方式是最佳的。

加载一个大文件比加载许多小文件包含更少的开销,而且因为它在我考虑创建一个全局 .js 文件并将其包含在 base.html 中的代码中看起来更干净(每个模板都继承自该文件) .但是,结果将是,JavaScript 会尝试分配所有事件绑定,即使事件应该绑定到的元素不在当前文档中。有了所有的 jQuery 选择器,它们就必须完成它们的工作,但效率不会太高。从早期的网络开发经验中,我知道可以做类似if(location.href == '/some/url/') { (JavaScript code) ... } 的事情。在这种情况下,这对我来说似乎不切实际,因为随着 URL 的更改,我必须更改 URLconf 和 .js 文件(同时使用 reverse() 和 {% url %} 以防止在其他地方发生这种情况)。我想这里不可能使用命名的 URL?

有没有人知道如何组织 JavaScript,一方面不为每个模板创建一个文件,又不降低不必要的性能?

【问题讨论】:

    标签: javascript jquery django


    【解决方案1】:

    我不知道这个问题是 Django 特有的——在各种系统中管理 Javascript 时都会遇到类似的问题。

    也就是说,我通常会尝试将我的 Javascript 文件分层,以便真正的全局脚本和库包含在一个文件中,特定于网站部分的脚本包含在一组特定于部分的文件中,并且特定于脚本单个页面包含在另一个页面特定文件的站点中(或内联代码,具体取决于上下文)。

    Django 对这种方法有很好的支持,因为您也可以对模板进行分层。在您的base.html 模板中包含全局脚本,然后创建一个继承自base.htmlmysection-base.html 模板,并添加特定于该部分的Javascript(和CSS)文件。然后该部分中的子页面可以继承自 mysection-base.html 而不是 base.html,并且它们都可以访问特定于部分的脚本。

    【讨论】:

    • 我猜这是最好的妥协。因为这也是我的 CSS 的组织方式,为了清楚起见,我也应该使用我的 JavaScript 这样做。
    【解决方案2】:

    我发现django-compressor 非常宝贵,因为它会自动压缩和缩小您的 JavaScript 和 CSS 预部署。它甚至会自动处理 SASS、LESS 和 CoffeeScript(如果它们漂浮在您的船上)。

    【讨论】:

    • 我不知道有这样的东西,特别是对于 Django。会仔细看看,谢谢!
    • django-compressor 是我们 100% 项目中包含的单个应用程序,它的价值不可估量。
    【解决方案3】:

    http://djangopackages.com/grids/g/asset-managers/ 的应用可能会有所帮助。

    【讨论】:

      【解决方案4】:

      您使用模块化 javascript。

      选择您选择的打包程序(我的是 browserify),它将您的所有模块打包到一个您可以压缩和 gzip 的包中。您将此文件发送到客户端并缓存。

      这意味着您已缓存所有代码,最大限度地减少 HTTP 请求并保持精简和高效。

      由于您有模块化代码,您只需像往常一样加载代码。

      我个人会使用一些表单特征检测来加载模块。您可以选择对几乎任何功能(一些 css 选择器、路由、url 段)进行功能检测。

      特征检测如下所示:

      var Features = {
        "class": "name",
        "class2": "name2",
        "dynamic-scroll": "dynamic-scroll",
        "tabstrip": "tabstrip",
        ...
      }
      
      for (var key in Features) {
        require(Features[key]);
      }
      

      davis 的路由看起来像

      Davis(function() {
        this.get("blog", function(req) {
          require("blog")(req);
        });
      
        this.get("blog/:post", function(req) {
          require("blog-post")(req);
        });
      
        this.get("shop", function(req) {
          require("shop")(req);
        });
        ...
      });
      

      您也可以尝试使用事件驱动架构。这意味着每个模块都绑定到事件

      // some-module
      
      mediator.on("blog-loaded", function() {
        // load in some libraries
      
        // construct some widgets
      
        mediator.emit("blog-ui-build", widgets);
      });
      

      而且您需要一些引导程序来启动事件循环。 Feel free to look at an EDA demo

      【讨论】:

      • 这对于较小的框架来说非常好,对于 django,我们有 django-compressor 可以更好地为您做到这一点。