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
Support provide/inject between Vue's Custom Elements (defineCustomElement) and Vue Components (defineComponent) #4476
Comments
To clarify, what is the case that is currently not working? Can you provide a code sample demonstrating a simplified case of what you intend to do? |
Thanks for looking into this! Here are multiple use cases I encountered : Use case: async componentAppContext.vue <template>
<slot />
</template>
<script setup>
// it could be a library like vue-i18n
provide('something', 'test')
</script> MyComponent.vue <script setup>
// inject fails. it should not.
const val = inject('something')
</script> main.ts customElements.define(
'my-app-context',
defineCustomElement(AppContext)
)
customElements.define(
'my-component',
defineCustomElement(defineAsyncComponent(() => import('MyComponent.vue')))
) index.html <html>
<body>
<my-app-context>
<my-component></my-component>
</my-app-context>
<script src="main.ts"></script>
</body>
</html> Use case: shared componentsAppContext.vue <template>
<slot />
</template>
<script setup>
// it could be a library like vue-i18n
provide('something', 'test')
</script> UtilComponent.vue <script setup>
// inject fails. it should not.
const val = inject('something')
</script> MyComponent.vue <template>
<UtilComponent />
</template> main.ts customElements.define(
'my-app-context',
defineCustomElement(AppContext)
)
customElements.define(
'my-component',
defineCustomElement(defineAsyncComponent(() => import('MyComponent.vue')))
) index.html <html>
<body>
<my-app-context>
<my-component></my-component>
</my-app-context>
<script src="main.ts"></script>
</body>
</html> I made a reproduction of both usecases here : https://github.com/gnuletik/vue-inject-deep Thanks! |
Still doesn't work in Vue 3 it seems? |
Yes. This has no real prioity for us - the real-life usecase is still cloudy. Personal Take: Your web components should not depend on a Vue-specific mechanism like provide/inject. Why turn your Vue Components into Web Components if you can only use them in other Vue apps because they depend on provide/inject? |
My usecase was to integrate Vue into a MVC framework like Django, which already provides its own template system.
Using an external mechanism (implementing Vue provide/inject into the app) would work if you don't want to use the existing Vue ecosystem because you can't call the |
I think the use cases described by @gnuletik are very realistic. EDIT, that actually works ⬇️ The offical vue documentation is a bit confusing in my opinon:
This means the parent provider component is a regular vue component and custom element is a child component which cannot inject the provided value. But it doesn't mention that it is also not possible to provide a value from a custom element down into a sub component of the custom element which is also a regular vue component but it lives in the same project as the parent custom element. You can get provide/inject to work if you use all child components of a custom element also as custom elements. That means you never use the EDIT end ⬆️ Unfortunately there is still no solution to use provide/inject between custom elements if they were lazy loaded. |
That seems to work fine: Playground |
You're right! Sorry for the wrong accusations. 💐 |
What problem does this feature solve?
As stated in the docs (https://v3.vuejs.org/guide/web-components.html#provide-inject), the Provide/Inject API only works between Vue's Custom Elements.
It makes it harder to use injected libraries inside custom elements.
The use case is :
What does the proposed API look like?
I've thought of several approaches to implement this.
1. Deep provide function
The provide function (https://github.com/vuejs/vue-next/blob/db1dc1c63097ed62a3f683a7a11c7e819d90bb73/packages/runtime-core/src/apiInject.ts#L58-L60) could search inside parent elements :
However, this can be a performance issue when heavily using provide/inject.
It could be enabled when needed as a function parameter like this :
but many libraries use
provide
insideuseLibrary()
-like functions. So, library developers would have to add thedeep
parameter too.To workaround this, this behavior may be manually enabled with a global configuration when required :
2. Implement an event based provide/inject API
The provide/inject API could be reworked with CustomEvents.
There's a current discussion about implement it as a standard : webcomponents-cg/community-protocols#2 so most questions are covered.
There may be other possibilities I did not think about.
Thanks for your work !
The text was updated successfully, but these errors were encountered: