主选项变更后如何清空JSON数据源场景下的Select2已选值
Select2级联下拉上级变更时下级残留旧值修复
问题现象
- 开发三级级联Select2下拉功能,预期效果为第一个下拉选项变更后,清空所有下级下拉框的选项与选中值
- 异常表现:第一个下拉选项变更时,第三个Select2下拉框仍保留之前选中的旧值,未被重置
原有实现代码
页面结构与依赖
<html lang="en"> <head> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet"/> <script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script> </head> <body> <select name="customerId" id="customerId"> <option value="">Seleccione</option> </select> <select name="customerDetail" id="customerDetail"></select> <select name="customerDetail2" id="customerDetail2"></select> </body> </html>
原有JS逻辑
let getCustomers = async (id, path) => { let data = [] await fetch(path) .then(response => response.json()) .then(response => { data = response.map((value, index) => { return { id: value.id, text: value.name } }) $(id).select2({ placeholder: "Seleccione", width: '250px', data: data }) }); return data } let getCustomerDetails = async (id, path, $el, field) => { let data = [] await fetch(path) .then(response => response.json()) .then(response => { let filter = response.filter((value, index) => { return ($el.value == value[field]) }) data.push({ id: 0, text: 'Seleccione', }) filter.forEach((value, index) => { data.push({ id: value.id, text: value.name }) }) $(id).empty() $(id).select2({ placeholder: "Seleccione", width: '250px', data: data }) }); return data } $(window).on('load', () => { $('select').select2({ placeholder: "Seleccione", width: '250px', }) getCustomers('#customerId', 'customers.json') $('#customerId').on('change', (e) => { let $element = e.target getCustomerDetails('#customerDetail', 'customersDetails.json', $element, 'customer_id') }) $('#customerDetail').on('change', (e) => { let $element = e.target getCustomerDetails('#customerDetail2', 'customersDetails.json', $element, 'customer_owner') }) })
测试用模拟数据
customers.json
[ { "id": 1, "name": "company demo" } ]
customersDetails.json
[ { "id": 1, "customer_id": 1, "customer_owner": 1, "name": "Customer detail 1" } ]
问题根因
- 一级下拉
#customerId的change事件仅重载了直接下级(二级下拉#customerDetail)的数据,未对三级下拉#customerDetail2做重置操作 - 重复初始化Select2前未销毁旧实例,组件内部状态缓存导致旧选中值残留
- 占位选项的id设置为
0,Select2会将其识别为有效选中值,无法正确显示placeholder - 组件值变更后未手动触发
change事件同步UI状态,导致显示值和实际选中值不一致
修复方案
- 封装通用Select2重置方法,统一处理实例销毁、选项清空、状态重置逻辑
- 上级下拉变更时,先重置所有后续层级的下拉,再加载直接下级的对应数据
- 修正占位选项id为空字符串,重载数据前销毁旧Select2实例,操作完成后触发change事件同步状态
修复后核心代码
通用重置方法
// 重置Select2到初始空状态 const resetSelect2 = (selectId) => { const $select = $(selectId); // 销毁已存在的Select2实例,清除缓存状态 if ($select.hasClass('select2-hidden-accessible')) { $select.select2('destroy'); } // 清空原生选项、重置选中值 $select.empty().val(null); // 重新初始化空状态Select2 $select.select2({ placeholder: "Seleccione", width: '250px', }); }
修改级联事件逻辑
$('#customerId').on('change', (e) => { const $element = e.target; // 先重置所有下级下拉 resetSelect2('#customerDetail'); resetSelect2('#customerDetail2'); // 选中有效值时才加载二级数据 if ($element.value) { getCustomerDetails('#customerDetail', 'customersDetails.json', $element, 'customer_id'); } }) $('#customerDetail').on('change', (e) => { const $element = e.target; // 先重置三级下拉 resetSelect2('#customerDetail2'); // 选中有效值时才加载三级数据 if ($element.value) { getCustomerDetails('#customerDetail2', 'customersDetails.json', $element, 'customer_owner'); } })
修改数据加载方法
let getCustomerDetails = async (id, path, $el, field) => { let data = [] await fetch(path) .then(response => response.json()) .then(response => { const filter = response.filter((value) => $el.value == value[field]); // 占位选项id设为空字符串,匹配placeholder逻辑 data.push({ id: '', text: 'Seleccione', }) filter.forEach((value) => { data.push({ id: value.id, text: value.name }) }) const $select = $(id); // 重载前销毁旧实例 if ($select.hasClass('select2-hidden-accessible')) { $select.select2('destroy'); } $select.empty(); $select.select2({ placeholder: "Seleccione", width: '250px', data: data }) // 默认选中占位项,触发change同步UI $select.val('').trigger('change'); }); return data }
内容的提问来源于stack exchange,提问作者Carlos Morales
相关产品推荐
相关产品推荐

