279 lines
9.6 KiB
JavaScript
279 lines
9.6 KiB
JavaScript
|
|
// 错误处理和兼容性脚本
|
|||
|
|
(function() {
|
|||
|
|
'use strict';
|
|||
|
|
|
|||
|
|
// 全局错误处理
|
|||
|
|
window.addEventListener('error', function(event) {
|
|||
|
|
console.error('Global error:', {
|
|||
|
|
message: event.message,
|
|||
|
|
filename: event.filename,
|
|||
|
|
lineno: event.lineno,
|
|||
|
|
colno: event.colno,
|
|||
|
|
error: event.error
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 发送错误到控制台(便于调试)
|
|||
|
|
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
|
|||
|
|
console.group('Error Details:');
|
|||
|
|
console.log('Message:', event.message);
|
|||
|
|
console.log('File:', event.filename);
|
|||
|
|
console.log('Line:', event.lineno + ':' + event.colno);
|
|||
|
|
if (event.error && event.error.stack) {
|
|||
|
|
console.log('Stack:', event.error.stack);
|
|||
|
|
}
|
|||
|
|
console.groupEnd();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return true; // 阻止默认错误处理
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// Promise 错误处理
|
|||
|
|
window.addEventListener('unhandledrejection', function(event) {
|
|||
|
|
console.error('Unhandled promise rejection:', event.reason);
|
|||
|
|
|
|||
|
|
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
|
|||
|
|
console.group('Promise Rejection:');
|
|||
|
|
console.log('Reason:', event.reason);
|
|||
|
|
if (event.reason && event.reason.stack) {
|
|||
|
|
console.log('Stack:', event.reason.stack);
|
|||
|
|
}
|
|||
|
|
console.groupEnd();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
event.preventDefault(); // 阻止默认处理
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// DOM 查询安全包装
|
|||
|
|
function safeQuerySelector(selector) {
|
|||
|
|
try {
|
|||
|
|
return document.querySelector(selector);
|
|||
|
|
} catch (e) {
|
|||
|
|
console.warn('Invalid selector:', selector, e);
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function safeQuerySelectorAll(selector) {
|
|||
|
|
try {
|
|||
|
|
return document.querySelectorAll(selector);
|
|||
|
|
} catch (e) {
|
|||
|
|
console.warn('Invalid selector:', selector, e);
|
|||
|
|
return [];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 安全的getElementById
|
|||
|
|
function safeGetElementById(id) {
|
|||
|
|
try {
|
|||
|
|
return document.getElementById(id);
|
|||
|
|
} catch (e) {
|
|||
|
|
console.warn('Invalid element ID:', id, e);
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 修复常见的兼容性问题
|
|||
|
|
function fixCompatibilityIssues() {
|
|||
|
|
// 修复classList不支持的情况(简化版本以避免Illegal invocation)
|
|||
|
|
try {
|
|||
|
|
// 安全检测classList支持
|
|||
|
|
var testElement = document.createElement('div');
|
|||
|
|
if (!testElement.classList) {
|
|||
|
|
// 简单的classList polyfill
|
|||
|
|
window.ClassListPolyfill = {
|
|||
|
|
addClass: function(element, className) {
|
|||
|
|
if (element && className) {
|
|||
|
|
var classes = element.className ? element.className.split(' ') : [];
|
|||
|
|
if (classes.indexOf(className) === -1) {
|
|||
|
|
classes.push(className);
|
|||
|
|
element.className = classes.join(' ').trim();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
removeClass: function(element, className) {
|
|||
|
|
if (element && className) {
|
|||
|
|
var classes = element.className ? element.className.split(' ') : [];
|
|||
|
|
var index = classes.indexOf(className);
|
|||
|
|
if (index !== -1) {
|
|||
|
|
classes.splice(index, 1);
|
|||
|
|
element.className = classes.join(' ').trim();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
hasClass: function(element, className) {
|
|||
|
|
if (!element || !className) return false;
|
|||
|
|
var classes = element.className ? element.className.split(' ') : [];
|
|||
|
|
return classes.indexOf(className) !== -1;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
// 如果检测失败,忽略错误
|
|||
|
|
console.warn('classList detection failed:', e);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 修复addEventListener不支持的情况
|
|||
|
|
if (!Element.prototype.addEventListener && Element.prototype.attachEvent) {
|
|||
|
|
Element.prototype.addEventListener = function(event, listener) {
|
|||
|
|
this.attachEvent('on' + event, listener);
|
|||
|
|
};
|
|||
|
|
Element.prototype.removeEventListener = function(event, listener) {
|
|||
|
|
this.detachEvent('on' + event, listener);
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 修复Array.from不支持的情况
|
|||
|
|
if (!Array.from) {
|
|||
|
|
Array.from = function(arrayLike) {
|
|||
|
|
var result = [];
|
|||
|
|
for (var i = 0; i < arrayLike.length; i++) {
|
|||
|
|
result.push(arrayLike[i]);
|
|||
|
|
}
|
|||
|
|
return result;
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 修复forEach不支持的情况
|
|||
|
|
if (!NodeList.prototype.forEach) {
|
|||
|
|
NodeList.prototype.forEach = function(callback, thisArg) {
|
|||
|
|
for (var i = 0; i < this.length; i++) {
|
|||
|
|
callback.call(thisArg, this[i], i, this);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检测浏览器支持情况
|
|||
|
|
function detectBrowserSupport() {
|
|||
|
|
const features = {
|
|||
|
|
es6: {
|
|||
|
|
arrow: false,
|
|||
|
|
const: false,
|
|||
|
|
let: false,
|
|||
|
|
template: false,
|
|||
|
|
destructuring: false
|
|||
|
|
},
|
|||
|
|
dom: {
|
|||
|
|
classList: (function() {
|
|||
|
|
try {
|
|||
|
|
var testElement = document.createElement('div');
|
|||
|
|
return !!testElement.classList;
|
|||
|
|
} catch (e) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
})(),
|
|||
|
|
querySelector: !!document.querySelector,
|
|||
|
|
addEventListener: !!window.addEventListener
|
|||
|
|
},
|
|||
|
|
css: {
|
|||
|
|
grid: typeof CSS !== 'undefined' && CSS.supports && CSS.supports('display', 'grid'),
|
|||
|
|
flexbox: typeof CSS !== 'undefined' && CSS.supports && CSS.supports('display', 'flex'),
|
|||
|
|
transform: typeof CSS !== 'undefined' && CSS.supports && CSS.supports('transform', 'translateX(0)')
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 测试ES6功能
|
|||
|
|
try {
|
|||
|
|
eval('const x = 1');
|
|||
|
|
features.es6.const = true;
|
|||
|
|
} catch (e) {}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
eval('let x = 1');
|
|||
|
|
features.es6.let = true;
|
|||
|
|
} catch (e) {}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
eval('`template`');
|
|||
|
|
features.es6.template = true;
|
|||
|
|
} catch (e) {}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
eval('() => {}');
|
|||
|
|
features.es6.arrow = true;
|
|||
|
|
} catch (e) {}
|
|||
|
|
|
|||
|
|
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
|
|||
|
|
console.group('Browser Support:');
|
|||
|
|
console.table(features);
|
|||
|
|
console.groupEnd();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return features;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 修复具体的错误
|
|||
|
|
function fixSpecificErrors() {
|
|||
|
|
// 确保所有必要的元素存在
|
|||
|
|
const requiredElements = [
|
|||
|
|
'navbar',
|
|||
|
|
'mobile-menu-button',
|
|||
|
|
'mobile-menu',
|
|||
|
|
'mobile-menu-overlay',
|
|||
|
|
'close-menu'
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
setTimeout(function() {
|
|||
|
|
requiredElements.forEach(function(id) {
|
|||
|
|
const element = document.getElementById(id);
|
|||
|
|
if (!element) {
|
|||
|
|
console.warn('Missing required element:', id);
|
|||
|
|
|
|||
|
|
// 尝试创建缺失的元素(某些情况下)
|
|||
|
|
if (id === 'mobile-menu-overlay' && !document.getElementById(id)) {
|
|||
|
|
const overlay = document.createElement('div');
|
|||
|
|
overlay.id = id;
|
|||
|
|
overlay.className = 'mobile-menu-overlay hidden';
|
|||
|
|
document.body.appendChild(overlay);
|
|||
|
|
console.log('Created missing overlay element');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}, 1000);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 安全的脚本加载
|
|||
|
|
function safeLoadScript(src, callback) {
|
|||
|
|
const script = document.createElement('script');
|
|||
|
|
script.src = src;
|
|||
|
|
script.onload = function() {
|
|||
|
|
if (callback) callback();
|
|||
|
|
};
|
|||
|
|
script.onerror = function() {
|
|||
|
|
console.error('Failed to load script:', src);
|
|||
|
|
};
|
|||
|
|
document.head.appendChild(script);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 初始化错误处理
|
|||
|
|
function init() {
|
|||
|
|
// 修复兼容性问题
|
|||
|
|
fixCompatibilityIssues();
|
|||
|
|
|
|||
|
|
// 检测浏览器支持
|
|||
|
|
detectBrowserSupport();
|
|||
|
|
|
|||
|
|
// 修复具体错误
|
|||
|
|
fixSpecificErrors();
|
|||
|
|
|
|||
|
|
// 为调试添加全局工具
|
|||
|
|
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
|
|||
|
|
window.debugTools = {
|
|||
|
|
safeQuerySelector: safeQuerySelector,
|
|||
|
|
safeQuerySelectorAll: safeQuerySelectorAll,
|
|||
|
|
safeGetElementById: safeGetElementById,
|
|||
|
|
fixCompatibilityIssues: fixCompatibilityIssues,
|
|||
|
|
detectBrowserSupport: detectBrowserSupport
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log('Error handler initialized');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 在DOM加载后初始化
|
|||
|
|
if (document.readyState === 'loading') {
|
|||
|
|
document.addEventListener('DOMContentLoaded', init);
|
|||
|
|
} else {
|
|||
|
|
init();
|
|||
|
|
}
|
|||
|
|
})();
|