解决Uncaught ReferenceError: tippy is not defined错误及方法检查方案
解决Watir注入Tippy时"tippy is not defined"错误
问题描述
使用Watir通过execute_script注入Popper和Tippy的样式表与脚本,为页面元素添加提示功能,但频繁抛出Uncaught ReferenceError: tippy is not defined错误,即使添加sleep 3也无法解决,需要在调用tippy方法前检查其是否正确定义。
原代码示例
require 'watir' b = Watir::Browser.new b.window.maximize b.goto 'URL' sleep 3 b.execute_script(" const popperStylesheet = document.createElement('link'); popperStylesheet.rel = 'stylesheet'; popperStylesheet.href = 'https://unpkg.com/@popperjs/core@2.11.6/dist/umd/popper.css'; const tippyStylesheet = document.createElement('link'); tippyStylesheet.rel = 'stylesheet'; tippyStylesheet.href = 'https://unpkg.com/tippy.js@6.3.3/dist/tippy.css'; const popperScript = document.createElement('script'); popperScript.src = 'https://unpkg.com/@popperjs/core@2.11.6/dist/umd/popper.js'; const tippyScript = document.createElement('script'); tippyScript.src = 'https://unpkg.com/tippy.js@6.3.3/dist/tippy.umd.js'; tippyScript.onload = function() { const customStyles = document.createElement('style'); customStyles.innerHTML = ` .custom-theme { background-color: #1c00d4; color: #ffffff; border-radius: 10px; } .custom-theme .tippy-arrow { color: #0012d4; } .tippy-box { background-color: Green; } .tippy-content { font-size: 20px; } `; var inputElement = document.getElementById('UserName'); if (inputElement) { console.log('Selected file:'); inputElement.addEventListener('focus', function() { inputElement._tippy.show(); }); tippy(inputElement, { content: 'Here you enter the first name, firstname should contain no numbers', theme: 'custom-theme', placement: 'right', arrow: true, duration: 300, delay: [500, 0], maxWidth: 200 }); } var headElement = document.getElementsByTagName("head")[0]; headElement.appendChild(popperStylesheet); headElement.appendChild(tippyStylesheet); headElement.appendChild(tippyScript); headElement.appendChild(popperScript); headElement.appendChild(customStyles); }; var headElement = document.getElementsByTagName("head")[0]; headElement.appendChild(popperStylesheet); headElement.appendChild(tippyStylesheet); headElement.appendChild(tippyScript); headElement.appendChild(popperScript); ")
报错信息
Uncaught ReferenceError: tippy is not defined at tippyScript.onload (eval at executeScript (login.do:476:16), <anonymous>:47:5)
问题根源与解决方法
核心问题
- 依赖加载顺序错误:Tippy依赖Popper,但原代码先添加Tippy脚本,再添加Popper脚本,导致Tippy加载时依赖未就绪。
- 重复注入脚本:
tippyScript.onload函数内再次添加所有脚本,造成重复加载和逻辑混乱。 - 未确保Tippy全局变量就绪:即使Tippy脚本加载完成,也可能因执行时机问题导致
tippy变量未挂载到全局。
解决方案
- 调整加载顺序:先注入Popper脚本,再注入Tippy脚本,确保依赖先加载完成。
- 移除重复注入逻辑:
onload函数内只处理Tippy初始化和样式添加,不再重复添加脚本。 - 检查Tippy全局变量:在调用
tippy前,通过typeof window.tippy !== 'undefined'检查是否定义,也可使用轮询确保变量就绪。 - 链式处理脚本加载:利用
onload事件确保Popper加载完成后再加载Tippy,避免异步加载的时序问题。
修改后的代码示例
require 'watir' b = Watir::Browser.new b.window.maximize b.goto 'URL' b.execute_script(" const headElement = document.getElementsByTagName('head')[0]; // 注入样式表 const popperStylesheet = document.createElement('link'); popperStylesheet.rel = 'stylesheet'; popperStylesheet.href = 'https://unpkg.com/@popperjs/core@2.11.6/dist/umd/popper.css'; headElement.appendChild(popperStylesheet); const tippyStylesheet = document.createElement('link'); tippyStylesheet.rel = 'stylesheet'; tippyStylesheet.href = 'https://unpkg.com/tippy.js@6.3.3/dist/tippy.css'; headElement.appendChild(tippyStylesheet); // 自定义样式 const customStyles = document.createElement('style'); customStyles.innerHTML = ` .custom-theme { background-color: #1c00d4; color: #ffffff; border-radius: 10px; } .custom-theme .tippy-arrow { color: #0012d4; } .tippy-box { background-color: Green; } .tippy-content { font-size: 20px; } `; headElement.appendChild(customStyles); // 先加载Popper,完成后加载Tippy const popperScript = document.createElement('script'); popperScript.src = 'https://unpkg.com/@popperjs/core@2.11.6/dist/umd/popper.js'; popperScript.onload = function() { const tippyScript = document.createElement('script'); tippyScript.src = 'https://unpkg.com/tippy.js@6.3.3/dist/tippy.umd.js'; tippyScript.onload = function() { // 检查tippy是否已定义 if (typeof window.tippy !== 'undefined') { const inputElement = document.getElementById('UserName'); if (inputElement) { inputElement.addEventListener('focus', function() { inputElement._tippy?.show(); // 使用可选链避免调用未定义方法 }); tippy(inputElement, { content: 'Here you enter the first name, firstname should contain no numbers', theme: 'custom-theme', placement: 'right', arrow: true, duration: 300, delay: [500, 0], maxWidth: 200 }); } } else { console.error('Tippy failed to load'); } }; headElement.appendChild(tippyScript); }; headElement.appendChild(popperScript); ")
关键改进点
- 先加载Popper脚本,在其
onload中加载Tippy,确保依赖就绪。 - 在Tippy的
onload中检查window.tippy是否存在,确认后再初始化提示。 - 使用可选链操作符
?.避免inputElement._tippy未定义时的报错。 - 移除重复的脚本注入逻辑,结构更清晰。
内容的提问来源于stack exchange,提问作者Rajagopalan
相关产品推荐
相关产品推荐

