
本文详解在启用 `type="module"` 的 html 环境下,如何安全、可靠地通过 `onblur` 事件获取 `` 元素的值,并解决因模块作用域、执行时机及事件绑定方式不当导致的 `undefined` 或 `cannot access 'document'` 等常见错误。
在现代前端开发中,使用 type="module" 加载 JavaScript 是推荐实践,但它带来两个关键约束:模块默认处于严格模式且具有顶层作用域隔离,同时 模块脚本默认延迟执行(deferred) —— 即 DOM 尚未完全解析完成时,模块代码可能已开始运行(尤其当 <script type="module"> 写在 <head> 中)。这正是你遇到问题的根本原因:</script>
- ❌ 错误写法:在 main.js 中直接调用 getFranchiseFee()(无参数),而该函数内部又试图访问 document.getElementById(...);
- ❌ 更严重的是:onblur="getFranchiseFee()" 是内联事件处理器,它运行在全局作用域,但你的 getFranchiseFee 函数仅在模块内声明并导出,全局不可见,因此浏览器会报 ReferenceError: getFranchiseFee is not defined;
- ✅ 正确思路:避免内联事件处理,改用模块内 addEventListener 绑定;确保 DOM 就绪后再操作元素;函数设计应接收事件对象或元素引用,而非重复查询 DOM。
✅ 推荐解决方案(模块化 + 事件委托)
1. 修改 HTML:移除内联 onblur,保留语义化结构
<td class="value">
<input
type="text"
class="form__field"
placeholder="R$"
name="franchise-fee"
id="franchiseFee"
required />
</td>⚠️ 注意:type="input" 是无效属性,应改为 type="text"(或 type="number" 更合适)。
2. 更新 GetElement.mjs(优化函数职责)
将一个或多个 UI 原型图、线框图、产品截图或设计稿转换为标准化、可直接交付的 PRD 风格文档,供产品、设计、前端和测试共同使用。适用于 Codex 需要分析 PC 网页、桌面端、移动端、响应式页面、独立弹窗、表单、表格、看板、数据大屏或多页面流程截图,还原页面结构与交互,强制套用固定文档模板,抽取跨页面共享规则,或把一组原型沉淀为单页规范文档加整体业务流程文档的场景。不适用于纯视觉审美点评、代码实现、接口设计、埋点方案、竞品分析或无 UI 输入的业务需求创作。
// GetElement.mjs
export function getFranchiseFee(inputElement) {
if (!inputElement || !(inputElement instanceof HTMLInputElement)) {
console.warn('Invalid input element passed to getFranchiseFee');
return NaN;
}
const value = inputElement.value.trim();
return value ? parseFloat(value) : 0;
}✅ 优势:函数只负责“解析值”,不耦合 DOM 查询逻辑,可复用、易测试。
3. 在 main.js 中安全绑定事件
// main.js
import { getFranchiseFee } from './GetElement.mjs';
// 确保 DOM 加载完成后再执行
document.addEventListener('DOMContentLoaded', () => {
const input = document.getElementById('franchiseFee');
if (!input) {
console.error('Input element with id "franchiseFee" not found');
return;
}
input.addEventListener('blur', (e) => {
const value = getFranchiseFee(e.target);
console.log('Franchise Fee (parsed):', value); // ✅ 正确输出数值
// 后续可触发计算、校验、更新 UI 等逻辑
});
});? 关键注意事项总结
- 永远不要依赖内联事件处理器(如 onblur="...")配合 ES 模块:模块内定义的函数无法被全局 HTML 属性访问;
- 始终检查 DOM 就绪状态:使用 DOMContentLoaded 或将 <script> 放在 </script>

















