【问题标题】:Django/jQuery: handling template inheritence and JS files loadingDjango/jQuery:处理模板继承和 JS 文件加载
【发布时间】:2015-09-21 01:34:50
【问题描述】:

在 Django 中,如何处理需要等待加载 JS 文件才能真正使用它的事实?

让我们看看这个例子的问题:

base.html

<!DOCTYPE html>
<html>

<head>...</head>
<body>
    {% include "content.html" %}

    <script src="jquery.js"></script>
    <script src="awesome-script.js"></script>
</body>
</html>

content.html

<script>
    $(document).ready(function(){
        ...
    });
</script>

这在逻辑上失败了 ($ is undefined)。我可以在调用脚本之前加载 jQuery,但我试图避免在我的主要内容之前加载 JS 文件,以尽可能快地加载网站。

那么,我该怎么办?谢谢。

【问题讨论】:

  • 我真的不理解您发布的代码。 content.htmlbase.html 有什么关系?如果它提供了{% block main-content %},那么显然在加载 jQuery 之前调用了脚本。
  • 是的,当然它之前被调用过(我用一个更明显的例子更新了代码)关键是我们需要在调用 JS 之前加载内容(为了不让页面变慢)但是在调用 content.html 中的脚本之前,我们必须等待所有 JS 加载完毕。
  • 或者如果 jquery 是在内容之前加载的唯一脚本,也许没关系?
  • 你不能清楚地期望 jQuery 脚本在 jQuery 被加载之前被执行。您必须更改脚本顺序。更新了答案。
  • 当然,如果我加载 jquery,然后是我的内容,然后是我的脚本,这会很好。但问题是:在加载我的内容之前加载 BIG Javascript 文件是否可以接受?我想这不是一个好习惯,我希望有更好的解决方案,我想我错了:)

标签: javascript jquery python django django-templates


【解决方案1】:

扩展 Wtower 的建议 - 让他接受。

我真的会坚持在他的示例中使用基于模板继承的方法。我想为该方法介绍更多元素,以涵盖其他一些常见需求:

<!DOCTYPE html>
<html>
<head>{% block scripts-head %}{% endblock %}</head>
<body>
    {% block content %}{% endblock %}
    {% block scripts %}
        <script src="jquery.js"></script>
    {% endblock %}
    <script>{% block script-inline %}{% endblock %}</script>
</body>
</html>

这里有3个想法:

  • 在标题中添加一个占位符,以防您在某些时候需要脚本。不言自明。
  • 在基本文件中包含常用脚本。如果它们很常见,则属于基本文件,您不必在每个模板中重复自己。然而你把它放在块内,所以它可以沿着层次结构被覆盖。

    {% extends "base.html" %}
    {% block scripts %}
        {{ block.super }}
        <script src="a-local-lib.js"></script>
    {% endblock %}
    

    关键在于使用{{ block.super }} 来引入在父模板中定义的任何脚本。当您的模板中有多个继承级别时,它尤其适用。您可以控制脚本是在继承的脚本之前还是之后。当然,如果您愿意,您可以完全覆盖该块,不包括 {{ block.super }}

  • 基本相同的想法,但使用原始 javascript。您可以以同样的方式使用它:每个需要包含一些内联 javascript 的模板都有其 {{ block script-inline }},并且将以 {{ block.super }} 开头,因此无论父级放入其中的内容仍然包含在内。

    例如,我在我的项目中使用 Ember,并且有几个初始化程序来设置项目设置和加载引导数据。我的基础应用加载模板有一个全局项目设置初始化程序,子模板定义本地设置和数据。

【讨论】:

  • 非常感谢,@spectras 让我度过了愉快的一天。
  • 同上。这正是我想要的。
【解决方案2】:

由于您的脚本使用 jQuery,您可以简单地使用 jQuery 的 $(document).ready()$(window).load() 函数分别在 DOM 准备好和所有窗口内容已加载的事件上绑定一个函数。

如果你不使用 jQuery,看看这些相关问题,了解如何用纯 JS 模仿上述行为:

编辑 1:包含顺序很重要。在执行任何需要 jQuery 的脚本之前,您必须包含 jQuery 脚本。

编辑 2:您可以通过将脚本与主要内容分开来更好地组织模板,或者使用第二个模板:

base.html

<!DOCTYPE html>
<html>

<head>...</head>
<body>
    {% include "content.html" %}
    {% include "js.html" %}
</body>
</html>

js.html

<script src="jquery.js"></script>
<script src="awesome-script.js"></script>
<script>
    $(document).ready(function(){
        ...
    });
</script>

(在这种情况下你渲染base.html

或使用(推荐):

base.html

<!DOCTYPE html>
<html>

<head>...</head>
<body>
    {% block content %}{% endblock %}
    {% block scripts %}{% endblock %}
</body>
</html>

content.html

{% extends 'base.html' %}
{% block content %}
    ...
{% endblock %}
{% block scripts %}
    <script src="jquery.js"></script>
    <script src="awesome-script.js"></script>
    <script>
        $(document).ready(function(){
            ...
        });
    </script>
{% endblock %}    

(在这种情况下你渲染content.html

【讨论】:

  • 谢谢。我确实使用了 jQuery,但它尚未加载,因此在调用 $(document) 时未定义“$”
  • 欢迎您,您只需在脚本之前包含 jquery 脚本即可。
  • 已经是这样了。在 base.html 中,加载了 Jquery,然后加载了我的脚本。但是进入我的主要内容时,根本没有加载任何JS(这很正常)
  • “进入主要内容”是什么意思?请张贴包含 jquery 的行。
猜你喜欢
  • 2011-04-12
  • 1970-01-01
  • 2011-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-28
  • 2011-09-14
相关资源
最近更新 更多