core icon indicating copy to clipboard operation
core copied to clipboard

defineCustomElement without shadowDom

Open Grafikart opened this issue 3 years ago • 31 comments

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
})

Grafikart avatar Aug 11 '21 17:08 Grafikart

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).

gnuletik avatar Aug 19 '21 19:08 gnuletik

@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.

dbaumannlt avatar Oct 04 '21 17:10 dbaumannlt

确实很想要这样的功能!!! 有的时候在使用别的原生JS工具时,别人写的东西要求渲染成element才能用(例如开发editor.js的插件)。这种时候要想vue配合起来,只能考虑defineCustomElement。 然而vue3的这个功能总是会有一个shadow-root,导致全局的样式根本无法对vue的渲染结果起作用。这就非常尴尬了。

conanliuhuan avatar Dec 14 '21 09:12 conanliuhuan

Please merge this PR. It's very useful function.

catsmeatman avatar Dec 22 '21 16:12 catsmeatman

Same here it is a huge need in our company or we will miss the train for vue3 and just go for lit

flozero avatar Jan 24 '22 05:01 flozero

@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 }))

gnuletik avatar Jan 25 '22 16:01 gnuletik

Is there a .js version of this? @gnuletik

Daniel-Vernon-55 avatar Feb 09 '22 00:02 Daniel-Vernon-55

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 avatar Feb 09 '22 00:02 gnuletik

@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?

image

yashwanth2714 avatar Dec 08 '22 14:12 yashwanth2714

@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

gnuletik avatar Dec 08 '22 14:12 gnuletik

@gnuletik Thank you!

yashwanth2714 avatar Dec 13 '22 07:12 yashwanth2714

This feature would really help for migrations of legacy projects to Vue, not every Vue app is build from scratch 😞

luckylooke avatar Apr 04 '23 10:04 luckylooke

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.

Buroni avatar May 11 '23 15:05 Buroni

++ 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.

mmazanec22 avatar May 11 '23 21:05 mmazanec22

Any update on this?

yoyo837 avatar May 11 '23 23:05 yoyo837

Any update on this?

NJgx avatar Jul 01 '23 02:07 NJgx

@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.

mjschranz avatar Jul 17 '23 18:07 mjschranz

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.

gnuletik avatar Jul 17 '23 23:07 gnuletik

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.

padcom avatar Sep 14 '23 11:09 padcom

There's also the issue of custom elements with shadowRoot inside forms - described here

padcom avatar Sep 14 '23 11:09 padcom

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?

onurusluca avatar Dec 15 '23 08:12 onurusluca

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.

kendru avatar Jan 11 '24 00:01 kendru

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

conanliuhuan avatar Jan 11 '24 05:01 conanliuhuan

Any news on this? This is quite a major issue - and a decision we can't understand to force a shadowRoot without a choice.

Our really bad work around is to set a mutation observer on

to watch for or

LukeBridges avatar Jan 23 '24 07:01 LukeBridges

@LukeBridges You might give the @padcom/vue3-ce-noshadow package a try. It is a hacked version of the defineCustomElement that allows you to create webcomponents that don't have the shadow DOM.

The implementation is taken from someone's branch who tried doing the exact same thing. There are a few caviats though. For example the slot API is different when you do webcomponents and you have to keep that in mind. This questionable implementation doesn't do anything with it. However, it is good enough for leaf components (ones that don't have other components slotted in).

Please check the sources at https://github.com/padcom/vue3-ce-noshadow

padcom avatar Jan 23 '24 22:01 padcom

this is the most critical feature i am missing in vue 3, this request is 3 years old and still no statement from core team? @yyx990803

volarname avatar Apr 23 '24 10:04 volarname

Same question here, what's the reason to force shadowDom? Anyone has a workaround on how to apply global styles without having to inject CSS in each and every Web Components?

lbineau avatar May 16 '24 08:05 lbineau

@yyx990803 Almost 3 years passed. Any update? Even just a sentence to explain why this is not an option.

cyfung1031 avatar May 16 '24 11:05 cyfung1031

The latest version of https://www.npmjs.com/package/vue-web-component-wrapper can now generate vue web component without Shadow DOM with slots and name slots

EranGrin avatar Jun 03 '24 11:06 EranGrin

The native slot function can only be used under the shadow dom....

LAMMUpro avatar Jun 30 '24 03:06 LAMMUpro