-
Notifications
You must be signed in to change notification settings - Fork 102
In CustomElements
, DOM #shadow-root
slot
semantics are not being honored, Vue is stepping on them
#49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
wrap
initialization and mutation are using this.children not this.shadowRoot.children?
[TL;DR spoiler alert, jump ahead one reply to a If you want to experiment, and try this yourself, the following patches to vue.js and vue-wc-wrapper.js are what you need:
Note: If you decide to use a "closed"
Bonus, for better efficiency and less side-effects, do this
and, for a cleaner version of the above use
That's it. Generally I've done a number of other things within Those changes are preparatory for creating a Vue plugin that shims |
As mentioned in the more recent-version of the original "issue posting" at the top of this page, I ended up creating a Vue Once I had gone through the task of fixing the design of In Smalltalk lingo, once I looked at the result of modifying
With that said, I started from scratch this morning and wrote a Vue plugin that takes-arg-options, shims The lightweight end-result is ~100 lines of code, one class, and the resulting native DOM The implementation also supports one of my goals of allowing seamless use of the existing A My sincere hope is that the Vue-team incorporates the required native |
wrap
initialization and mutation are using this.children not this.shadowRoot.children?CustomElements
, DOM #shadow-root
slot
semantics are not being honored, Vue is stepping on them
@smallscript This is amazing, and exactly what I was looking for. Perfect timing too! Going to give your plugin / modified vue.js a shot. |
I found a workaround for this that doesn't require any modifications to Vue or plug-ins and it appears to be working across all major browsers. Basically just wire up the |
I've had this issue too and forked the library to make it actually function somewhat correctly: https://github.com/GiG/vue-web-component-wrapper (readme isn't updated). Because I wanted to get something working (until a real solution came along) it's not overly thought out and includes some code specific to what we're working on at the moment. It was somewhat easy though to add real slot support in vue without modifying Vue itself by modifying the toVNodes method to output real slot elements instead of the child component dom when it finds slotted children. https://github.com/GiG/vue-web-component-wrapper/blob/master/src/utils.js#L68 (modified toVNodes method). Great write up and explanation, I do hope this is looked into from Vue itself as quite honestly in it's current form exporting web components from vue just doesn't work as you would expect. |
First of all, thanks @TomCaserta for your great job fixing the library. We are using this lib as part of the cross technologies (React, Vue, Angular, native, etc.) compatibility feature of a front-end framework based on Vue as you can see here Power-Solutions/power-solutions-frontend-framework#2. We decide to use Vue because of the community, activity, and compatibility, but we will not follow this project on Vue if there is no community support. @TomCaserta and others had proposed specific solutions for this, but nothing has been done. So please, if you can not do anything for now or this project is dead, SAY SOMETHING!!!. Sorry for the emotional speaking but I think that when you own wide used repositories, you have a responsibility too. Thanks for all, hope you answer soon. |
We are also running into the similar issues when using slot along with we are using an external webcomponent library (which is using stencilJS) in our VueJS (^2.6.10) repo. An example would be like this,
Now the |
@LinusBorg You mention in issue #93 (comment) Vue 3 supports built in Custom Elements with the new wrapper implementation but I am curious, does this implementation address this slots override issue? I am running into a use case where this seems to be what is happening.
I am attempting to develop a custom element library using Vue 3's My implementation looks something like this:
with the custom-element component file (customElement.ce.vue):
and the element.js file where the custom element is declared:
and the rendered html output of the new component.
where there is no longer a 'slot' attribute on the slot inside |
TL;DR
Issue:
vue-web-component-wrapper
prevents aWebComponent
#shadow-root
from containing DOM renderedslot
elements.In its implementation, the
wrap
function it provides is focused on creatingCustomElements
tags that behave asVueComponents
; rather than focusing on behaving asWebComponents
defined from aVueComponent
that integrates, with shadow-DOM semantics, as a direct child-element in their#shadow-root
definition.Note:
The following discussion assumes some familiarity with the DOM concepts
slot
,light DOM
andshadow DOM
.The Vue system has
VueComponents
(similar to classes) that are based onvueDefinitions
associated with atagName
usingVue.component(tagName, vueDefinition)
. I will be referring to theseVueComponents
as HTML macros, from here on.When you create a new
$root
vue
usingnew Vue(vueDefinition)
with ael:
member in thevueDefinition
(or manually invoke its'$mount
), Vue will walk the childElements and recursively perform macro substitution of all the elements whosetagName
matches theVueComponents
you registered usingVue.component(tagName, vueDefinition)
. It will continue to perform this behavior based on reactive change tracking from that point on.It does this using the
render
function defined on thevueDefinition
.If no
render
function is defined, it will look for atemplate
to compile into arender
function. If notemplate
is defined, it will extract theinnerHTML
of the correspondingtagName
element, and use that as thetemplate
.The browser DOM allows you to define
CustomElements
andWebComponents
.To enable that, it provides the
customElements
API to allow registering a Javascriptclass
as the behavior for an element with a hyphenatedtagName
.A custom element once registered is a new type of browser DOM element; depending on your browser, custom elements technology is the same technique by which it internally implements a number of the intrinsic browser elements with closed
#shadow-roots
.A custom element is not a macro and thus can't do some of the things Vue
VueComponents
can, but aWebComponent
using a shadow DOM#shadow-root
can provide some capabilities that VueVueComponents
cannot. This can be specifically seen in how it uses DOMslot
elements, and how it lazily upgradestagName
elements when a corresponding custom element is registered, and in how it encapsulates the#shadow-root
elements includingcss
.When you issue the call:
you are defining a
CustomElement
. If thatCustomElement
will utilize a#shadow-root
then you are defining aWebComponent
. AWebComponent
usesslot
elements within the#shadow-root
for slotting (transposing) theinnerHTML
(DOMNodes
) contained within any HTML that has thattagName
element.What's the problem, why should I think about these things?
Given that background we now have the foundation to understand why
wrap
does not provide expectedWebComponent
#shadow-root
semantics and behavior, but does allow self-containedCustomElement
isolated$root
wrappering of VueVueComponent
vueDefinitions
.Basically, Vue thinks that any
slot
elements it sees within avue
subtree ofVNodes
areslot
elements that it should always use as its (Vue's) own macro element directives for performing transpositional replacement ofinnerHTML
content into a render/template definition.That behavior leads to a direct conflict with the DOM semantics of
slot
elements in#shadow-roots
.The text was updated successfully, but these errors were encountered: