使用JavaScript为隐藏input数组元素赋值(谷歌地图自动补全场景)
问题根因
赋值失效完全由JavaScript作用域规则导致,和Google Maps Autocomplete的能力无关:
- 初次实现时,
viaLatitude/viaLongitude是document.getElementsByName()返回的类数组NodeList,并非单个DOM元素。直接对该类数组调用.value赋值,只是给对象本身新增了一个自定义属性,完全没有操作到页面上真实的隐藏input节点,存储的值自然无法被表单读取。 - 调整为循环实现后,你用
var声明的循环下标i、Autocomplete实例viaAutocomplete都是函数级作用域,不随循环迭代生成独立作用域。整个循环执行完成后,所有后续触发的place_changed事件、异步回调中拿到的i永远等于循环终止值(即via_route.length),此时viaLatitude[i]、viaLongitude[i]在类数组中根本不存在,赋值操作不会产生任何实际效果。 service.textSearch是异步接口调用,等响应返回执行回调时,同样会引用到被全局覆盖后的i值,就算变量没有越界,也会给错误下标的元素赋值。
正确实现逻辑
核心是固定每个循环迭代的独立作用域,让事件触发、异步回调时都能准确拿到当前迭代对应的下标、Autocomplete实例、隐藏input节点,不要引用被循环覆盖的全局变量。
修正后可直接运行的代码
// 确保Google Maps Places API完全初始化后执行以下代码 const viaRouteInputs = document.getElementsByName('via_route[]'); const viaLatInputs = document.getElementsByName('via_route_lat[]'); const viaLngInputs = document.getElementsByName('via_route_long[]'); // 初始化PlaceService实例,传入空DOM节点作为容器 const placeService = new google.maps.places.PlacesService(document.createElement('div')); // 用let声明块级作用域变量,让每个迭代的变量独立不被覆盖 for (let i = 0; i < viaRouteInputs.length; i++) { const currentAddressInput = viaRouteInputs[i]; // 为每个地址输入框独立创建Autocomplete实例 const currentAutocomplete = new google.maps.places.Autocomplete(currentAddressInput, { types: ['address'] }); // 为每个实例绑定独立的place_changed事件 currentAutocomplete.addListener('place_changed', () => { const place = currentAutocomplete.getPlace(); // 提前缓存当前迭代对应的经纬度input节点 const currentLatInput = viaLatInputs[i]; const currentLngInput = viaLngInputs[i]; if (place.hasOwnProperty('place_id')) { if (!place.geometry) return; // 给当前对应的真实input节点赋值 currentLatInput.value = place.geometry.location.lat(); currentLngInput.value = place.geometry.location.lng(); } else { // 异步调用时直接引用缓存的input节点,避免闭包作用域问题 placeService.textSearch({ query: place.name }, (results, status) => { if (status === google.maps.places.PlacesServiceStatus.OK) { currentLatInput.value = results[0].geometry.location.lat(); currentLngInput.value = results[0].geometry.location.lng(); } }); } }); }
效果验证
赋值完成后,可在控制台打印三个input数组的取值确认写入正常:
console.log('途经点地址数组值:', [...viaRouteInputs].map(el => el.value)); console.log('途经点纬度数组值:', [...viaLatInputs].map(el => el.value)); console.log('途经点经度数组值:', [...viaLngInputs].map(el => el.value));
只要控制台能打印出每个下标的对应值,表单提交时就会正常携带所有隐藏input的数组值,不会出现取值为空的问题。
内容的提问来源于stack exchange,提问作者عبداللہ بن عباس قرات اکیڈمی
相关产品推荐
相关产品推荐

