django-components如何仅加载当前页面所用组件的JS文件?
解决django-components仅加载当前页面组件JS依赖的问题
方法一:通过组件基类追踪已加载组件,自定义标签输出依赖
1. 创建带追踪功能的组件基类
所有组件继承这个基类,渲染时自动将组件名加入上下文的追踪集合:
# components/base.py from django_components import Component class TrackedComponent(Component): def render(self, context): # 初始化或更新已加载组件集合 if 'loaded_components' not in context: context['loaded_components'] = set() context['loaded_components'].add(self.__class__.__name__) return super().render(context)
示例组件继承写法:
# components/button.py from .base import TrackedComponent class ButtonComponent(TrackedComponent): template_name = "components/button.html" js = "components/button.js" # 其他组件逻辑...
2. 自定义模板标签输出仅已加载组件的JS
在你的app下创建templatetags目录,添加component_tags.py:
# yourapp/templatetags/component_tags.py from django import template from django_components.registry import registry register = template.Library() @register.simple_tag(takes_context=True) def used_component_js(context): loaded_components = context.get('loaded_components', set()) js_output = [] # 遍历已加载组件,收集对应的JS文件 for comp_class_name in loaded_components: component = registry.get(comp_class_name) if component and component.js: # 处理单个JS字符串或列表的情况 if isinstance(component.js, str): js_output.append(component.js) else: js_output.extend(component.js) # 去重并生成script标签 unique_js_files = list(set(js_output)) return '\n'.join(f'<script src="{js_path}"></script>' for js_path in unique_js_files)
3. 在模板中使用自定义标签
替换原来的{% component_js_dependencies %},改为:
{% load component_tags %} <!-- 页面内容,渲染所需组件 --> {% component "button" %} <!-- 仅加载当前页面用到的组件JS --> {% used_component_js %}
方法二:利用组件渲染的返回值手动收集依赖(适合单个页面场景)
如果只是个别页面需要,可以在渲染组件时捕获实例,手动收集JS:
{% component "button" as button_comp %} {% component "card" as card_comp %} <!-- 输出收集到的JS --> {% for js_file in button_comp.js %} <script src="{{ js_file }}"></script> {% endfor %} {% for js_file in card_comp.js %} <script src="{{ js_file }}"></script> {% endfor %}
这种方法适合页面组件少的场景,缺点是每个组件都要手动处理,不够通用。
注意事项:
- 确保组件的
js属性配置正确,支持单个字符串或列表形式 - 如果使用静态文件,记得用
{% static %}标签包裹JS路径,比如组件中写成js = static("components/button.js")
内容的提问来源于stack exchange,提问作者jmauperin
相关产品推荐
相关产品推荐

