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

Webpack更新后TomSelect首次动态添加选项不显示问题

问题:TomSelect首次动态填充选项后页面不更新,二次操作恢复正常

我有两个选择字段,第一个字段变更时会动态填充第二个字段。更新Webpack和Encore后,首次切换第一个字段时,第二个字段的TomSelect实例已正确加载选项,但页面上看不到;第二次切换第一个字段时,功能完全正常。

环境信息

Symfony 6.4.10 with Twig.
System:
  OS: Windows 10 10.0.19045
Binaries:
  Node: 18.12.1
  Yarn: 1.22.22
  npm: 8.19.2
Browsers:
  Chrome: Chromium (127.0.6533.72)
  Firefox: 128.0.3
Packages:
  postcss-loader: ^7.0.1 => 7.3.3
  sass-loader: ^13.0.2 => 13.3.2
  webpack: ^5.* => 5.93.0
  webpack-cli: ^5.* => 5.1.4
  webpack-notifier: ^1.15.0 => 1.15.0
  tom-select: ^2.* => 2.3.1,

第一个选择框代码

<select id="demand_cosAgency" name="demand[cosAgency]"
        class="form-control-sm tomselected ts-hidden-accessible">
    <option value="" selected="selected">- 选择机构 -</option>
    <option value="141">Label 141</option>
    <option value="183">Label 183</option>
    <option value="197">Label 197</option>
    ...
</select>

第二个选择框代码

<select id="demand_client" name="demand[client]"
        class="form-control-sm tomselected ts-hidden-accessible">
    <option value="">- 请先选择机构 -</option>
</select>

AJAX回调中的JavaScript代码

const tomSelectInstance = document.getElementById('demand_client').tomselect;
tomSelectInstance.clear();
tomSelectInstance.clearOptions();
tomSelectInstance.clearCache();
tomSelectInstance.settings.maxOptions = null;

console.log(response.responseJSON.agencyClients);

$.each(response.responseJSON.agencyClients, (k, v) => {
  tomSelectInstance.addOption({ value: k, text: v });
});

tomSelectInstance.settings.placeholder = '- 选择客户 -';
tomSelectInstance.open();

console.log(tomSelectInstance.options);

tomSelectInstance.clearCache();
tomSelectInstance.sync();
tomSelectInstance.refreshOptions();

控制台输出结果

console.log(response.responseJSON.agencyClients)输出:

{
    "2340": "Label text",
    "2341": "Another label text",
    "2342": "blablabla",
    "2343": "text text"
    (...)
}

console.log(tomSelectInstance.options)输出:

{
    "2340": {
        "value": "2340",
        "text": "Label text",
        "$order": 1,
        "$id": "demand_client-opt-1",
        "$div": {div#demand_client-opt-1.option.active}
    },
    "2341": {
        "value": "2341",
        "text": "Another label text",
        "$order": 2,
        "$id": "demand_client-opt-2",
        "$div": {div#demand_client-opt-2.option}
    },
    "2342": {
        "value": "2342",
        "text": "blablabla",
        "$order": 3,
        "$id": "demand_client-opt-3",
        "$div": {div#demand_client-opt-3.option}
    },
    "2343": {
        "value": "2343",
        "text": "text text",
        "$order": 4,
        "$id": "demand_client-opt-4",
        "$div": {div#demand_client-opt-4.option}
    }
    (...)
}

首次调用后页面中不存在#demand_client-opt-*.option元素,第二次调用则正常显示。已尝试添加setTimeout,但无任何效果。


解决方案

1. 强制触发组件渲染

TomSelect的refreshOptions()可能未完全触发DOM更新,在现有操作末尾添加render()方法强制重新渲染:

// 在refreshOptions之后添加
tomSelectInstance.render();

2. 检查Webpack模块导入完整性

更新Webpack后可能存在Tree Shaking导致的功能缺失,确保完整导入TomSelect:

  • 导入完整CSS文件:
    import 'tom-select/dist/css/tom-select.default.css';
    
  • 避免按需导入,直接完整引入:
    import TomSelect from 'tom-select';
    

3. 批量添加选项替代循环单加

循环调用addOption可能导致DOM更新延迟,改用addOptions批量插入:

// 替换原有的$.each循环
const options = Object.entries(response.responseJSON.agencyClients).map(([k, v]) => ({
  value: k,
  text: v
}));
tomSelectInstance.addOptions(options);

4. 初始化时启用即时渲染

在TomSelect初始化时添加render: true配置,确保组件初始化时完成DOM渲染:

new TomSelect('#demand_client', {
  render: true,
  // 其他配置项
});

内容的提问来源于stack exchange,提问作者Patryk Godowski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 07:50:06