You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过JS更新Twig变量实现无刷新分类筛选?

筛选广告列表的AJAX实现方案

问题描述

我在Twig模板中通过for循环渲染一个对象数组(adList),希望实现筛选功能:选择分类后无需刷新页面,仅显示所选分类的广告。目前已实现通过AJAX将筛选参数传给Symfony控制器,控制器处理后返回JSON,前端能获取到响应。

相关代码:

控制器传递变量到Twig

return $this->render('@Ad/ad_list.html.twig', [
    'adList' => $adList,
]);

AJAX请求代码

$.ajax({
   url : $form.attr('action'),
   type: "POST",
   data : filters,
   complete: function(html) {
        console.log(html['responseJSON'])
   }
});

控制器返回JSON响应

$response = JsonResponse::fromJsonString($jsonContent);
$response->prepare($request);
$response->send();

Twig渲染列表

{% for ad in adList|slice(0, 9) %}
    <!-- 广告内容渲染 -->
{% endfor %}

问题:是否可以通过JS更新Twig的adList变量来重新渲染列表?


解决方案

不行,JS无法直接修改Twig变量。因为Twig是服务端渲染模板,页面加载完成后,Twig变量已经被编译成静态HTML,前端JS只能操作DOM,无法直接访问服务端的Twig变量。以下是三种可行的实现方式:

方案1:前端用JSON数据手动渲染DOM

给Twig渲染的列表添加容器,拿到AJAX返回的JSON后,生成新的HTML替换原有内容:

  1. 修改Twig模板,添加容器:
<div id="ad-list-container">
  {% for ad in adList|slice(0, 9) %}
    <div class="ad-item">
      <h3>{{ ad.title }}</h3>
      <p>{{ ad.description }}</p>
      <!-- 其他广告字段 -->
    </div>
  {% endfor %}
</div>
  1. 修改AJAX代码:
$.ajax({
  url: $form.attr('action'),
  type: "POST",
  data: filters,
  dataType: 'json',
  success: function(filteredAdList) {
    const container = $('#ad-list-container');
    container.empty(); // 清空原有列表
    
    // 遍历JSON数据生成HTML
    filteredAdList.forEach(ad => {
      const adItem = `
        <div class="ad-item">
          <h3>${ad.title}</h3>
          <p>${ad.description}</p>
        </div>
      `;
      container.append(adItem);
    });
  }
});

方案2:控制器返回Twig模板片段

把广告列表的渲染逻辑抽成独立模板片段,控制器根据请求类型返回完整页面或模板片段:

  1. 创建模板片段@Ad/ad_list_fragment.html.twig:
{% for ad in adList|slice(0, 9) %}
  <div class="ad-item">
    <h3>{{ ad.title }}</h3>
    <p>{{ ad.description }}</p>
  </div>
{% endfor %}
  1. 修改控制器逻辑:
use Symfony\Component\HttpFoundation\Request;

public function filterAds(Request $request)
{
    // 处理筛选逻辑,得到filteredAdList
    
    if ($request->isXmlHttpRequest()) {
        // AJAX请求返回模板片段
        return $this->render('@Ad/ad_list_fragment.html.twig', [
            'adList' => $filteredAdList,
        ]);
    }
    
    // 非AJAX请求返回完整页面
    return $this->render('@Ad/ad_list.html.twig', [
        'adList' => $filteredAdList,
    ]);
}
  1. 修改AJAX代码:
$.ajax({
  url: $form.attr('action'),
  type: "POST",
  data: filters,
  success: function(html) {
    $('#ad-list-container').html(html); // 直接替换为返回的HTML片段
  }
});

方案3:前端使用Twig.js复用模板语法

如果想复用Twig的渲染逻辑,可引入Twig.js(与Twig语法兼容),控制器返回JSON数据,前端用Twig.js渲染:

  1. 引入Twig.js库,创建前端模板:
<script src="https://cdn.jsdelivr.net/npm/twig@1.17.1/dist/twig.min.js"></script>
<script type="text/twig-template" id="ad-list-template">
  {% for ad in adList|slice(0, 9) %}
    <div class="ad-item">
      <h3>{{ ad.title }}</h3>
      <p>{{ ad.description }}</p>
    </div>
  {% endfor %}
</script>
  1. 修改AJAX代码:
$.ajax({
  url: $form.attr('action'),
  type: "POST",
  data: filters,
  dataType: 'json',
  success: function(filteredAdList) {
    const template = Twig.twig({ id: 'ad-list-template' });
    const html = template.render({ adList: filteredAdList });
    $('#ad-list-container').html(html);
  }
});

内容的提问来源于stack exchange,提问作者Szymon D.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 20:40:55