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
相关产品推荐
相关产品推荐

