You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用变量优化document.getElementById,减少RPG骰子工具重复代码?

简化RPG骰子工具的下拉菜单处理代码

我用JavaScript写了一款桌面RPG骰子工具,现在想在添加新功能前简化代码、移除冗余内容。目前工具通过下拉菜单修改掷骰设置,每个菜单都对应独立函数,用document.getElementById把选中值存到全局变量里,现在已经有8个这类菜单,之后还要新增更多,同时要适配同系统的其他游戏(菜单ID和变量名会变更)。

我不想给每个菜单都写新函数,能不能把菜单ID存到变量里,插入到document.getElementById中?比如把MoonSettingSelected = document.getElementById("MoonPhaseMenu");改成类似let SelectedSetting = document.getElementById(SelectedMenu);的形式。我试过用QuerySelectorAll获取菜单数据,但觉得getElementById更好用,我是JavaScript新手。


示例HTML代码

<div class="centre RageOptions">
  <select id="MoonPhaseMenu" onclick="SetMoonPhase()" class="menu shadow">
    <option value="9999" selected>Moon phase</option>
    <option value="1">Full</option>
    <option value="2">Crescent</option>
    <option value="3">Half</option>
    <option value="4">Gibbous</option>
    <option value="5">New</option>
  </select>
</div>
<p>&nbsp</p>
<div>
  <div class="centre RageOptions">
    <select id="AuspiceMenu" onclick="SetAuspice()" class="menu shadow">
      <option value="9999" selected>Auspice</option>
      <option value="1">Ahroun</option>
      <option value="2">Theurge</option>
      <option value="3">Philodox</option>
      <option value="4">Galliard</option>
      <option value="5">Ragabash</option>
    </select>
  </div>
  <p>&nbsp</p>
  <div class="centre RageOptions">
    <select id="RankMenu" onclick="SetRank()" class="menu shadow">
      <option value="9999" selected>Rank</option>
      <option value="0">Cub (0)</option>
      <option value="1">Cliath (1)</option>
      <option value="2">Fostern (2)</option>
      <option value="3">Adren (3)</option>
      <option value="4">Athro (4)</option>
      <option value="5">Elder (5)</option>
      <option value="6">Legend (6)</option>
    </select>
  </div>
</div>

示例JavaScript代码

// CHANGE GLOBAL VARIABLES ON MENU SELECT

var MoonSetting = "9999";
var AuspiceSetting = "9999";
var GarouRank = Number(0);

function SetMoonPhase() {
  let MoonSettingSelected = document.getElementById("MoonPhaseMenu");
  MoonSettingSelected.addEventListener("change", function handleChange(event) {
    MoonSetting = Number(event.target.value);
  });
}

function SetAuspice() {
  AuspiceSettingSelected = document.getElementById("AuspiceMenu");
  AuspiceSettingSelected.addEventListener(
    "change",
    function handleChange(event) {
      AuspiceSetting = Number(event.target.value);
    }
  );
}

function SetRank() {
  // Set GarouRank global variable on menu change
  GarouRankSelected = document.getElementById("GarouRankMenu");
  GarouRankSelected.addEventListener("change", function handleChange(event) {
    GarouRank = Number(event.target.value);
  });
}

// …and repeat for 5 (and counting) functions, each of which is identical except for the ID in getElementById("…")

优化方案

1. 统一管理菜单与全局变量的映射

先创建一个配置对象,把每个菜单ID和对应的全局变量关联起来,彻底摆脱重复函数:

// 用对象封装所有设置,避免零散全局变量污染作用域
const settings = {
  MoonSetting: "9999",
  AuspiceSetting: "9999",
  GarouRank: 0
};

// 菜单ID与对应设置字段的映射表,新增菜单只需要加一条
const menuMappings = [
  { menuId: "MoonPhaseMenu", settingKey: "MoonSetting" },
  { menuId: "AuspiceMenu", settingKey: "AuspiceSetting" },
  { menuId: "RankMenu", settingKey: "GarouRank" }
];

2. 编写通用事件绑定函数

写一个通用函数遍历映射表,自动给每个菜单绑定change事件,更新对应设置:

function setupMenuHandlers() {
  menuMappings.forEach(mapping => {
    const menu = document.getElementById(mapping.menuId);
    if (!menu) return; // 避免找不到元素报错

    menu.addEventListener("change", (event) => {
      // 根据字段类型转换值,比如GarouRank需要转数字
      const value = mapping.settingKey === "GarouRank" 
        ? Number(event.target.value) 
        : event.target.value;
      settings[mapping.settingKey] = value;
    });
  });
}

// 页面加载完成后初始化所有菜单
document.addEventListener("DOMContentLoaded", setupMenuHandlers);

3. 简化HTML,移除冗余属性

原来的onclick属性可以直接删掉,因为初始化函数会自动完成事件绑定:

<div class="centre RageOptions">
  <select id="MoonPhaseMenu" class="menu shadow">
    <option value="9999" selected>Moon phase</option>
    <option value="1">Full</option>
    <option value="2">Crescent</option>
    <option value="3">Half</option>
    <option value="4">Gibbous</option>
    <option value="5">New</option>
  </select>
</div>
<p>&nbsp</p>
<div>
  <div class="centre RageOptions">
    <select id="AuspiceMenu" class="menu shadow">
      <option value="9999" selected>Auspice</option>
      <option value="1">Ahroun</option>
      <option value="2">Theurge</option>
      <option value="3">Philodox</option>
      <option value="4">Galliard</option>
      <option value="5">Ragabash</option>
    </select>
  </div>
  <p>&nbsp</p>
  <div class="centre RageOptions">
    <select id="RankMenu" class="menu shadow">
      <option value="9999" selected>Rank</option>
      <option value="0">Cub (0)</option>
      <option value="1">Cliath (1)</option>
      <option value="2">Fostern (2)</option>
      <option value="3">Adren (3)</option>
      <option value="4">Athro (4)</option>
      <option value="5">Elder (5)</option>
      <option value="6">Legend (6)</option>
    </select>
  </div>
</div>

优化优势

  • 新增菜单时,只需要在menuMappings里加一条映射,不用写新函数
  • 代码冗余度大幅降低,维护和扩展更轻松
  • 用DOMContentLoaded确保页面元素加载完成后再绑定事件,避免找不到元素的问题
  • 保留了你偏好的getElementById,逻辑清晰直观
  • 适配其他游戏时,只需要修改settings对象和menuMappings数组即可

内容的提问来源于stack exchange,提问作者Richard Cosgrove

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 23:02:30