如何链式触发jQuery的change事件?
解决jQuery异步操作后的链式change事件触发问题
我之前也碰到过类似的困扰——想要通过修改一个元素的值来链式触发后续元素的change事件,但要么因为DOM更新不及时,要么因为异步操作没完成,导致触发时机不对,事件没法正常生效。
最初的同步场景问题
最开始你尝试的是三个input的链式触发:
<input id="one"> <input id="two"> <input id="three">
$('#one').change(function() { $('#two').val('change_by_one'); $('#two').trigger('change'); }); $('#two').change(function() { $('#three').val('changed'); });
你提到直接触发change时#two的新值尚未渲染导致状态异常,其实同步设置val()后DOM是立即更新的,可能这个场景下的问题更多是后续逻辑的依赖,但当遇到异步加载内容的实际场景时,这个问题会变得更突出。
实际异步场景的痛点
比如你后来给出的下拉框示例:选择组织后,通过异步请求(用setTimeout模拟)加载媒体选项到第二个下拉框,然后希望自动触发它的change事件来更新input的值。但直接在#organisation的change事件里调用$media.change()是没用的,因为异步操作还没执行完,下拉框里还没有新选项,触发change事件时拿不到正确的值。
<select id="organisation"> <option value="org1">org1</option> <option value="org2">org2</option> </select> <select id='media'> </select> <input placeholder="get the selected media"/>
var $media = $('#media'); $('#organisation').change(function() { var options = []; setTimeout(function() { $media.append('<option value="image" data-type="image">image</option>'); $media.append('<option value="first" data-type="video">video</option>'); }, 1000); $media.change(); // 这里异步还没完成,触发无效 }); $('#media').change(function() { $('input').val($('#media').val()); });
解决方案:用Promise等待异步操作完成
把异步加载选项的逻辑封装成Promise,就能精准控制触发change事件的时机——只有当选项完全渲染到DOM后,再触发change事件,这样后续的逻辑就能拿到正确的内容了。
最终实现代码:
<select id="organisation"> <option value="org1">org1</option> <option value="org2">org2</option> </select> <select id='media'> </select> <input placeholder="get the selected media"/>
var $media = $('#media'); $('#organisation').change(function() { AddOptions().then(function() { $media.change(); // 异步完成后再触发change }); }); $('#media').change(function() { $('input').val($('#media').val()); }); function AddOptions() { return new Promise(function(resolve, reject) { setTimeout(function() { $media.find('option').remove().end(); // 先清空旧选项 $media.append('<option value="image" data-type="image">image</option>'); $media.append('<option value="first" data-type="video">video</option>'); resolve(); // 异步操作完成,通知Promise }, 1000); }); };
这里的核心逻辑是:
- 把添加选项的异步逻辑包装成返回Promise的函数
AddOptions - 在
#organisation的change事件里,等待AddOptions()的Promise完成(也就是选项渲染完毕),再调用$media.change() - 这时
#media的change事件触发时,下拉框已经有了新选项,就能正确把选中值同步到input里
内容的提问来源于stack exchange,提问作者alba hoo




