-
Notifications
You must be signed in to change notification settings - Fork 546
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
Web Components #220
Comments
At least in Vue 2 (and it seems to me in Vue 3 too) it's possible to build a component as a Web Component. With Then you can use this WC in your app. |
@ShGKme correct me if I'm wrong, but doesn't it build a Vue entry point as a standalone WC for consumption in any web apps? Rather, I'm interested in using native WC for components internal to an app, where those components would be efficiently merged into -- and have access to -- their parent Vue context. |
Honestly, this is the least meaningful direction I see for WCs - it really only creates a ton of extra complexity in return for... very little (as of now). At least for me, it's a trade-off I have absolutely no interest in pursuing unless it actually reduces the overall complexity in achieving the same end result. |
That said you can build your WC-based framework using Vue's reactivity system + template layer (or with other templating solutions, e.g. https://github.com/yyx990803/vue-lit) |
I'm gonna explore how much can be done without touching Vue core, i.e. in a library, or what the minimal core changes would be to support such a library.
Thanks for the pointer. That really ain't the same as what I have in mind, as those WC are totally disconnected from Vue. E.g. you couldn't use your directives in there nor inject stuff from DI. |
@jods4 I use a large library of Custom Elements in my Vue app every day and have had other teams doing the same. From what I gather you're mostly looking for a way to avoid this problem: "a hard boundary at your custom element (your Vue app stops right here), you'd have to create a new Vue app instance for each custom element." |
@jfbrennan I was thinking more of the consequences of having 2 distinct Vue apps running (host and custom element). I was prob. unclear because shadow dom totally is a "hard boundary" (for events, styles, etc.) FWIW Vue 3.2 now has some custom element support, but it's geared more towards external usage, with one Vue app inside each custom element. With that work being done, I wonder if Evan could now make an "internal mode". I'm thinking It's a bit of a niche, but using custom elements to build some core components (low-level controls) can have some benefits, such as extending built-in elements (free ARIA and more). |
Vue has always worked well with Custom Elements afaik, it's one reason I use it instead of React. I don't understand why you have more than one Vue "app". Are you instantiating another Vue app inside Custom Elements? |
2022 update: now Vue supports instancing "Vue Components" as true "Web Components" by using I would like to make the following feedback on this feature: For example: I was looking to create a web component to get access to Another example could be creating a custom form control that integrates with the native Getting access to these requires having access to the component import { vueCustomComponent } from "vue"
export class MyComponent extends vueCustomComponent(HTMLInputElement) {
// ...
} Or merge user-provided prototype into the class: export default defineCustomComponent(
/* component: */ { },
/* prototype: */ { disconnectedCallback() { } }) The API also forces usage of shadow DOM, which sometimes we may not want as it creates boundaries for CSS, DOM queries and events. Would be nice if we could decide to use a component without template nor shadow DOM (just a wrapper around its actual content). |
EDIT 2022: Vue eventually got some support for creating Web Components, and the shortcomings of current situation is better described in this comment of mine below.
I'm opening this issue to start a high-level discussion about potential ways of integrating native Web Component with Vue.
Context
I'm interested in using native Web Components (WC) as an internal building block inside large Vue applications.
The following are interesting but not my focus here:
Why Web Components?
"Vue has its own component system, why do you want WC inside your app?"
The web platform is increasingly built with WC as a primitive for further features.
Well-known examples included Scoped Styles, without pre-processing tricks, true DOM encapsulation, or extending built-in elements.
More new-ish examples include Element Internals, which is a spec that lets you:
:disabled
,:invalid
CSS states, take part in form validation, submission, reset, and more.These can be pretty useful and I'd only expect more in the future.
Current limitations
Nothing prevents you from creating a WC in JS code.
As long as you configure Vue compiler to recognize the tag name isn't a Vue component, everything should work just fine.
IMHO where this is lacking is when it comes to integrating your WC implementation with the rest of your app.
Most likely, you'll want to implement the contents of your custom element using Vue itself, as you're already using it for the rest of the app.
Because there's a hard boundary at your custom element (your Vue app stops right here), you'd have to create a new Vue app instance for each custom element. This is a bit wasteful.
Worse, because it's 2 different apps, there's stuff that won't work at all, most notably injection (DI).
What Vue could provide
I think it would be interesting if Vue could optionally instantiate its component as custom elements and inject itself into them so that it flows seamlessly.
Imagine you could add
customElement: true
to your component definition and Vue would:Then there's "comfort" APIs as, let's be honest, the native WC API are a pain to use. E.g. if props could optionally be reflected as attributes by Vue, if adding
shadowDom: 'closed'
would do what it says, etc.I wonder to what extend this would need core Vue support vs could be implemented in a user-land library.
I'm just throwing the idea here, there are a bunch of challenges/designs to address, e.g. how would
this
representing the custom element surface insetup
, to be used in API such asattachInternals()
?Thoughts?
The text was updated successfully, but these errors were encountered: