Safari browser does not support build-in custom elements, only anonymous custom elements.
Compatibility is shown in the following figure.
That is, Safari only supports the following HTML-formatted UI components by default.
The following web components components, which extend on native HTML elements via the is
attribute, are not supported.
That’s a problem, otherwise great UI components are verbose and tedious when they can only be implemented using anonymous custom elements.
Or, be ruthless and ignore the Safari user community, which you can, and just wait to be fired.
So, the best solution is to make the Safari browser support the development of built-in custom element components as well.
How to do it?
Polyfill build-in custom element
The solution is relatively simple, there is a special polyfill, just introduce it.
Project address.
https://github.com/WebReflection/custom-elements-builtin
For scenarios where custom elements are supported, but not built-in custom elements, mainly for the Safari browser.
The index.js is a non-compressed version and es.js is a compressed version.
When using it, you can directly use it as follows.
However, if
judgment plus document.write
is not a good use, but we can’t directly quote //unpkg.com/@webreflection/custom-elements-builtin from this address.
According to the author, browser characteristics are always changing, and it is not reliable to do browser type determination.
This is true, but instead of making a browser distinction, we can just make a distinction based on API characteristics.
So, I made a built-in judgment process for the original JS code.
The judgment logic is shown in the following code.
|
|
It is safe to judge based on features, the return value of isSupportBuildIn
will be true if the browser supports built-in custom elements, and undefined if the browser does not.
The optimized JS code I have open sourced and put on gitee, see: https://gitee.com/zhangxinxu/build-in-custom-element-polyfill
Problems with perfect operation
This Polyfill is really amazing, the original Web Components code does not need any modification, the component function is perfectly supported in Safari browser, and all components are working well.
Then, when it comes to the business code, the problem is found when the components are passed with references.
For example, the referenced code is as follows.
The myComponent.someMethod() method executes fine in browsers that natively support built-in custom elements.
However, in Safari, it reports an error and undefined cannot be executed as a function.
The reason for this is that the implementation of safari-polyfill.js has a limitation that makes the initialization of custom elements occur later than in native browsers.
That is, in Safari, when the myComponent.someMethod()
method is executed, the myComponent
element has not yet become a built-in custom element.
As a result, the execution will error out.
My workaround is to trigger a custom 'connected'
event in the connectedCallback lifecycle function, so that the element is already componentized when the business code is executed by binding the 'connected'
event.
The code is illustrated in the code section of the component.
Then, the business code is transformed to look like this.
This ensures that the component must have been initialized by the time the someMethod() method is executed.
Reference https://www.zhangxinxu.com/wordpress/2021/04/safari-buildin-custom-element-polyfill/