如何解决p5.js中全局变量locID赋值后外部仍未定义的问题?
问题解决:选择器联动时全局变量初始化访问异常
问题情况
我开发的应用包含两个下拉选择器:
- 第一个选择器从JSON文件加载地点数据,选中选项时将对应ID存入全局声明的
locID变量 - 第二个选择器从JSON加载工作坊数据,仅展示与
locID匹配的内容
遇到的问题:在setup函数中初始化第二个选择器阶段,访问locID结果为undefined;尝试将let改为var后问题仍未解决。
原代码如下:
let locID; let select; let select2; function preload() { data = loadJSON( "https://raw.githubusercontent.com/mia-mmt2-2223/leesfestival/main/festival.json" ); } function setup() { createCanvas(400, 400); //LOCATION SELECTION //create select element with as options name from locations from json select = createSelect(); select.position(10, 10); select.option("Select a location"); for (let i = 0; i < data.locations.length; i++) { select.option(data.locations[i].name); } //when a location is selected, save the location id select.changed(function () { item = select.value(); for (let i = 0; i < data.locations.length; i++) { if (data.locations[i].name == item) { locID = data.locations[i].id; } } }); //WORKSHOP SELECTION //create select element with as options name from workshops where location matches locID from json select2 = createSelect(); select2.position(10, 50); select2.option("Select a workshop"); for (let i = 0; i < data.workshops.length; i++) { if (data.workshops[i].location == locID) { select2.option(data.workshops[i].name); } } }
问题原因
setup函数执行时,用户还未对第一个选择器进行操作,locID变量还未被赋值,因此初始化第二个选择器的筛选逻辑会因为locID为undefined而无法匹配到任何工作坊。而且原代码中第二个选择器的选项只在setup中初始化一次,不会随着locID的变化自动更新。
解决方案
把第二个选择器的选项更新逻辑抽成独立函数,每次第一个选择器的值变化时,先更新locID,再重新渲染第二个选择器的选项:
修改后的代码:
let locID; let select; let select2; function preload() { data = loadJSON( "https://raw.githubusercontent.com/mia-mmt2-2223/leesfestival/main/festival.json" ); } function setup() { createCanvas(400, 400); // 地点选择器初始化 select = createSelect(); select.position(10, 10); select.option("Select a location"); for (let i = 0; i < data.locations.length; i++) { select.option(data.locations[i].name); } // 地点选择变化时的处理 select.changed(function () { const selectedName = select.value(); // 找到选中地点对应的ID for (let i = 0; i < data.locations.length; i++) { if (data.locations[i].name === selectedName) { locID = data.locations[i].id; break; // 找到后直接跳出循环,提升效率 } } // 更新工作坊选择器的选项 updateWorkshopSelect(); }); // 工作坊选择器初始化(仅添加默认选项) select2 = createSelect(); select2.position(10, 50); select2.option("Select a workshop"); } // 负责更新工作坊选择器选项的函数 function updateWorkshopSelect() { // 清空原有选项(保留默认选项) select2.remove(); // 先移除旧的选择器元素 select2 = createSelect(); select2.position(10, 50); select2.option("Select a workshop"); // 筛选并添加匹配locID的工作坊选项 if (locID !== undefined) { for (let i = 0; i < data.workshops.length; i++) { if (data.workshops[i].location === locID) { select2.option(data.workshops[i].name); } } } }
关键修改点
- 新增
updateWorkshopSelect函数,负责重新创建工作坊选择器并筛选匹配locID的选项 - 在地点选择器的
changed事件中,找到对应locID后立即调用updateWorkshopSelect更新选项 - 初始化工作坊选择器时只添加默认提示选项,避免在
locID未赋值时执行无效筛选 - 新增
break语句优化地点ID查找逻辑,找到匹配项后立即停止循环
内容的提问来源于stack exchange,提问作者Driek van der Meulen
相关产品推荐
相关产品推荐

