如何通过JavaScript检测MDC-Web组件是否被浏览器支持?
Absolutely, you can absolutely do this—feature detection is far more reliable than browser sniffing for this kind of problem, especially since Samsung Browser often mimics Chrome's user agent string. Here's how to approach it properly:
1. Check for MDC Component-Specific Dependencies
Most MDC-Web components rely on specific browser APIs or DOM behaviors. For the MDC Select component (which is giving you trouble), you can test the core features it needs to function:
function isMDCSelectSupported() { // Check for critical DOM APIs MDC Select depends on if (!('closest' in Element.prototype)) return false; if (!('CustomEvent' in window)) return false; if (!('getComputedStyle' in window)) return false; // Test if select elements can properly trigger change events (a common pain point in Samsung Browser) const testSelect = document.createElement('select'); testSelect.innerHTML = '<option value="1">Test</option><option value="2">Test 2</option>'; document.body.appendChild(testSelect); let changeFired = false; testSelect.addEventListener('change', () => changeFired = true); // Simulate a user-driven change (some browsers ignore programmatic index changes without an event) testSelect.dispatchEvent(new Event('change', { bubbles: true })); const supportsChangeEvents = changeFired; document.body.removeChild(testSelect); // Test support for CSS features MDC Select uses (like pointer-events for custom dropdowns) const testStyle = document.createElement('style'); testStyle.textContent = '.mdc-test { pointer-events: auto; }'; document.head.appendChild(testStyle); const testDiv = document.createElement('div'); testDiv.className = 'mdc-test'; document.body.appendChild(testDiv); const supportsPointerEvents = window.getComputedStyle(testDiv).pointerEvents === 'auto'; document.body.removeChild(testDiv); document.head.removeChild(testStyle); return supportsChangeEvents && supportsPointerEvents; }
Call this function early in your app. If it returns false, you can fall back to a native <select> or a simpler alternative.
2. Test Component Initialization Directly
Another robust method is to attempt to initialize a minimal version of the MDC component and verify it works as expected. This catches edge cases where individual APIs work, but their combination breaks the component:
function testMDCComponentSupport(componentConstructor) { try { // Create a minimal, valid DOM structure for the component const testElement = document.createElement('div'); // Tailor the DOM to the component (here, MDC Select) if (componentConstructor === mdc.select.MDCSelect) { testElement.className = 'mdc-select'; testElement.innerHTML = ` <div class="mdc-select__anchor"> <span class="mdc-select__ripple"></span> <span class="mdc-floating-label">Test</span> <span class="mdc-select__selected-text"></span> <span class="mdc-select__dropdown-icon"> <svg viewBox="7 10 10 5"> <polygon points="7 10 12 15 17 10"></polygon> </svg> </span> <span class="mdc-line-ripple"></span> </div> <div class="mdc-select__menu mdc-menu-surface"> <ul class="mdc-list" role="listbox"> <li class="mdc-list-item" data-value="1" role="option"> <span class="mdc-list-item__text">Option 1</span> </li> </ul> </div> `; } document.body.appendChild(testElement); // Attempt to initialize the component const component = new componentConstructor(testElement); // Verify key functionality exists (e.g., MDC Select's open/close methods) const isSupported = component && typeof component.open === 'function' && typeof component.close === 'function'; // Clean up component.destroy(); document.body.removeChild(testElement); return isSupported; } catch (err) { // Initialization failed = component isn't supported console.warn('Component support test failed:', err); return false; } } // Usage example for MDC Select const selectIsSupported = testMDCComponentSupport(mdc.select.MDCSelect); if (!selectIsSupported) { // Fallback logic: replace MDC Selects with native ones, or load a polyfill document.querySelectorAll('.mdc-select').forEach(selectEl => { // Swap out the MDC Select DOM with a native <select> const nativeSelect = document.createElement('select'); // Copy options from the MDC Select's menu selectEl.querySelectorAll('.mdc-list-item').forEach(item => { const option = document.createElement('option'); option.value = item.dataset.value; option.textContent = item.querySelector('.mdc-list-item__text').textContent; nativeSelect.appendChild(option); }); selectEl.parentNode.replaceChild(nativeSelect, selectEl); }); }
3. Avoid User-Agent Sniffing (Unless Absolutely Necessary)
While you could check for "SamsungBrowser" in navigator.userAgent, this is fragile—browser vendors often change UA strings, and newer versions of Samsung Browser might fix the issue. Use this only as a last resort if feature detection doesn't catch the edge case:
function isSamsungBrowser() { return /SamsungBrowser/i.test(navigator.userAgent); }
Final Notes
- Always test your fallback behavior thoroughly in the problematic browser.
- Check the MDC-Web component documentation for any official support checks (some components expose an
isSupported()static method).
内容的提问来源于stack exchange,提问作者Megidd

