defineCustomElement without shadowDom
What problem does this feature solve?
With the 3.2 release we can now define customElement using Vue but it uses a shadowRoot. It could be nice to be able to create custom element without this shadowRoot so It can use the app CSS (even if it means loosing the slot capability)
What does the proposed API look like?
To avoid breaking changes we could use an option for defineCustomElement
const MyVueElement = defineCustomElement({
// normal Vue component options here
}, {
shadowRoot: false
})
Also looking forward this proposal !
As of today, I did not find any way to share CSS across multiple components using Vue+Vite (CSS @import
are processed by postcss-import
on Vite, which inlines shared CSS in each component).
@yyx990803 This is a critical feature for my current client. We are developing web components that will be served by a Content Management System where the CSS will be included in the header of the page. Not being able to pierce the veil of the shadow root is a show stopper. We are currently using Vue 2 with the following package https://github.com/karol-f/vue-custom-element.
The author has indicated that they are not creating a Vue 3 compatible package because defineCustomElement is provided Vue3. Please provide this support in Vue 3.
确实很想要这样的功能!!! 有的时候在使用别的原生JS工具时,别人写的东西要求渲染成element才能用(例如开发editor.js的插件)。这种时候要想vue配合起来,只能考虑defineCustomElement。 然而vue3的这个功能总是会有一个shadow-root,导致全局的样式根本无法对vue的渲染结果起作用。这就非常尴尬了。
@jsbaguette, you can copy the apiCustomElement.ts
file from my PR if you need it.
You just need to replace an import in this file :
- import { hydrate, render } from '.'
+ import { hydrate, render } from '@vue/runtime-dom'
And install an extra dependency :
npm install --save html-parsed-element
Then, you can import this local file in your codebase.
- import { defineCustomElement } from 'vue'
+ import { defineCustomElement } from './localApiCustomElement.ts'
We use it in production.
EDIT:
You also need to specify the optional argument introduced in the PR to skip shadow DOM :
import MyComponent from './MyComponent.vue'
- customElements.define('my-component', defineCustomElement(MyComponent))
+ customElements.define('my-component', defineCustomElement(MyComponent, { shadowRoot: false }))
Is there a .js version of this? @gnuletik
I don't think so.
However, you can easily transpile it:
mkdir /tmp/vue && cd /tmp/vue
curl https://raw.githubusercontent.com/vuejs/core/4b3aed23e687c9d77d4fdcac537be15443a9a608/packages/runtime-dom/src/apiCustomElement.ts > apiCustomElement.ts
yarn add typescript
# errors from tsc can be ignored
yarn run tsc -m esnext apiCustomElement.ts
# there you go
cat apiCustomElement.js
@gnuletik - Thanks for providing the workaround.
We are seeing the following type errors while trying this in our project. Could you please tell us how to fix them?
@yashwanth2714 Vue typescript config seems different than the one on your repo. You can ignore TS errors by adding the following line at the top of localApiCustomElement.ts
:
// @ts-nocheck
This feature would really help for migrations of legacy projects to Vue, not every Vue app is build from scratch 😞
This feature would also be useful as shadow DOM doesn't work with many popular libraries such as plotly.js. I've wanted to use Vue 3's web components for several years now but have been blocked by this limitation.
++ to needing this feature for use with popular libraries. This would be helpful for my company's project to incrementally replace legacy WordPress functionality with a Vue app that handles payments and user account management. Stripe elements cannot be mounted in a shadow root.
@gnuletik Reviving an old thread here, but by chance did that PR you write here only work for specific versions?
I'm actually writing a vuejs webcomponent that will consume HTML (that includes vuejs components inside it) from a CMS to be used in an Angular app.
As it stands right now I'm trying to use the file you mentioned in your PR with changes mentioned but sadly it doesn't want to work.
Hi @mjschranz, I'm not sure about the latest versions of Vue. I did not test it. You may have a chance to make it work by rebasing the PR on main.
I'm facing the same issue and also with components that are rendered based on content from a CMS. I am using GrapesJS as the page editor and having custom elements with reactivity is a blessing by comparison to creating all of the logic from scratch.
However, since there are multiple pages in a single site, it is absolutely necessary that the styling falls through to the custom elements. This means the shadowRoot
is very much not wanted in this case.
In the documentation is says that custom elements created with vue.js are 100% compatible. IMHO they're more like 50% there, since the shadowRoot
isn't a strict requirement for them to exist.
There's also the issue of custom elements with shadowRoot
inside forms - described here
Any update on this? I want the user to be able to change the styling of my custom element with their CSS, but with shadow DOM it doesn't seem to be possible?
Any update on this? I want the user to be able to change the styling of my custom element with their CSS, but with shadow DOM it doesn't seem to be possible?
I also want a fix to this so that I can use Tailwind CSS utility classes within my Vue 3 Web Components. However, there is a way to allow users to change selective portions of your styles using the part attribute within your component and having your users use the ::part pseudo-selector in their styles.
Any update on this? I want the user to be able to change the styling of my custom element with their CSS, but with shadow DOM it doesn't seem to be possible?
通过createApp后直接mount的方式挂载,可避免shadowRoot。这可能算是一个Hack方法。不过我用起来很有效。感兴趣的话可以看一下我的博客: https://blog.panda-studio.cn/vue_web_component_webpack_compiler