Skip to content

Commit 83a0cf1

Browse files
committed
3.5: custom elements
1 parent 444c780 commit 83a0cf1

File tree

4 files changed

+106
-48
lines changed

4 files changed

+106
-48
lines changed

.vitepress/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ export const sidebar: ThemeConfig['sidebar'] = {
421421
{
422422
text: 'Advanced APIs',
423423
items: [
424+
{ text: 'Custom Elements', link: '/api/custom-elements' },
424425
{ text: 'Render Function', link: '/api/render-function' },
425426
{ text: 'Server-Side Rendering', link: '/api/ssr' },
426427
{ text: 'TypeScript Utility Types', link: '/api/utility-types' },

src/api/custom-elements.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Custom Elements API {#custom-elements-api}
2+
3+
## defineCustomElement() {#definecustomelement}
4+
5+
This method accepts the same argument as [`defineComponent`](#definecomponent), but instead returns a native [Custom Element](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) class constructor.
6+
7+
- **Type**
8+
9+
```ts
10+
function defineCustomElement(
11+
component:
12+
| (ComponentOptions & CustomElementsOptions)
13+
| ComponentOptions['setup'],
14+
options?: CustomElementsOptions
15+
): {
16+
new (props?: object): HTMLElement
17+
}
18+
19+
interface CustomElementsOptions {
20+
styles?: string[]
21+
22+
// the following options are 3.5+
23+
configureApp?: (app: App) => void
24+
shadowRoot?: boolean
25+
nonce?: string
26+
}
27+
```
28+
29+
> Type is simplified for readability.
30+
31+
- **Details**
32+
33+
In addition to normal component options, `defineCustomElement()` also supports a number of options that are custom-elements-specific:
34+
35+
- **`styles`**: an array of inlined CSS strings for providing CSS that should be injected into the element's shadow root.
36+
37+
- **`configureApp`** <sup class="vt-badge" data-text="3.5+"/>: a function that can be used to configure the Vue app instance for the custom element.
38+
39+
- **`shadowRoot`** <sup class="vt-badge" data-text="3.5+"/>: `boolean`, defaults to `true`. Set to `false` to render the custom element without a shadow root. This means `<style>` in custom element SFCs will no longer be encapsulated.
40+
41+
- **`nonce`** <sup class="vt-badge" data-text="3.5+"/>: `string`, if provided, will be set as the `nonce` attribute on style tags injected to the shadow root.
42+
43+
Note that instead of being passed as part of the component itself, these options can also be passed via a second argument:
44+
45+
```js
46+
import Element from './MyElement.ce.vue'
47+
48+
defineCustomElement(Element, {
49+
configureApp(app) {
50+
// ...
51+
}
52+
})
53+
```
54+
55+
The return value is a custom element constructor that can be registered using [`customElements.define()`](https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/define).
56+
57+
- **Example**
58+
59+
```js
60+
import { defineCustomElement } from 'vue'
61+
62+
const MyVueElement = defineCustomElement({
63+
/* component options */
64+
})
65+
66+
// Register the custom element.
67+
customElements.define('my-vue-element', MyVueElement)
68+
```
69+
70+
- **See also**
71+
72+
- [Guide - Building Custom Elements with Vue](/guide/extras/web-components#building-custom-elements-with-vue)
73+
74+
- Also note that `defineCustomElement()` requires [special config](/guide/extras/web-components#sfc-as-custom-element) when used with Single-File Components.
75+
76+
## useHost() <sup class="vt-badge" data-text="3.5+"/> {#usehost}
77+
78+
A Composition API helper that returns the host element of the current Vue custom element.
79+
80+
## useShadowRoot() <sup class="vt-badge" data-text="3.5+"/> {#useshadowroot}
81+
82+
A Composition API helper that returns the shadow root of the current Vue custom element.
83+
84+
## this.$host <sup class="vt-badge" data-text="3.5+"/> {#this-host}
85+
86+
An Options API property that exposes the host element of the current Vue custom element.

src/api/general.md

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -225,46 +225,3 @@ Define an async component which is lazy loaded only when it is rendered. The arg
225225
```
226226
227227
- **See also** [Guide - Async Components](/guide/components/async)
228-
229-
## defineCustomElement() {#definecustomelement}
230-
231-
This method accepts the same argument as [`defineComponent`](#definecomponent), but instead returns a native [Custom Element](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) class constructor.
232-
233-
- **Type**
234-
235-
```ts
236-
function defineCustomElement(
237-
component:
238-
| (ComponentOptions & { styles?: string[] })
239-
| ComponentOptions['setup']
240-
): {
241-
new (props?: object): HTMLElement
242-
}
243-
```
244-
245-
> Type is simplified for readability.
246-
247-
- **Details**
248-
249-
In addition to normal component options, `defineCustomElement()` also supports a special option `styles`, which should be an array of inlined CSS strings, for providing CSS that should be injected into the element's shadow root.
250-
251-
The return value is a custom element constructor that can be registered using [`customElements.define()`](https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/define).
252-
253-
- **Example**
254-
255-
```js
256-
import { defineCustomElement } from 'vue'
257-
258-
const MyVueElement = defineCustomElement({
259-
/* component options */
260-
})
261-
262-
// Register the custom element.
263-
customElements.define('my-vue-element', MyVueElement)
264-
```
265-
266-
- **See also**
267-
268-
- [Guide - Building Custom Elements with Vue](/guide/extras/web-components#building-custom-elements-with-vue)
269-
270-
- Also note that `defineCustomElement()` requires [special config](/guide/extras/web-components#sfc-as-custom-element) when used with Single-File Components.

src/guide/extras/web-components.md

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,15 @@ export default {
4747
```js
4848
// vue.config.js
4949
module.exports = {
50-
chainWebpack: config => {
50+
chainWebpack: (config) => {
5151
config.module
5252
.rule('vue')
5353
.use('vue-loader')
54-
.tap(options => ({
54+
.tap((options) => ({
5555
...options,
5656
compilerOptions: {
5757
// treat any tag that starts with ion- as custom elements
58-
isCustomElement: tag => tag.startsWith('ion-')
58+
isCustomElement: (tag) => tag.startsWith('ion-')
5959
}
6060
}))
6161
}
@@ -81,7 +81,7 @@ The primary benefit of custom elements is that they can be used with any framewo
8181

8282
### defineCustomElement {#definecustomelement}
8383

84-
Vue supports creating custom elements using exactly the same Vue component APIs via the [`defineCustomElement`](/api/general#definecustomelement) method. The method accepts the same argument as [`defineComponent`](/api/general#definecomponent), but instead returns a custom element constructor that extends `HTMLElement`:
84+
Vue supports creating custom elements using exactly the same Vue component APIs via the [`defineCustomElement`](/api/custom-elements#definecustomelement) method. The method accepts the same argument as [`defineComponent`](/api/general#definecomponent), but instead returns a custom element constructor that extends `HTMLElement`:
8585

8686
```vue-html
8787
<my-vue-element></my-vue-element>
@@ -171,6 +171,20 @@ Inside the component, slots can be rendered using the `<slot/>` element as usual
171171

172172
The [Provide / Inject API](/guide/components/provide-inject#provide-inject) and its [Composition API equivalent](/api/composition-api-dependency-injection#provide) also work between Vue-defined custom elements. However, note that this works **only between custom elements**. i.e. a Vue-defined custom element won't be able to inject properties provided by a non-custom-element Vue component.
173173

174+
#### App Level Config <sup class="vt-badge" data-text="3.5+" /> {#app-level-config}
175+
176+
You can configure the app instance of a Vue custom element using the `configureApp` option:
177+
178+
```js
179+
defineCustomElement(MyComponent, {
180+
configureApp(app) {
181+
app.config.errorHandler = (err) => {
182+
/* ... */
183+
}
184+
}
185+
})
186+
```
187+
174188
### SFC as Custom Element {#sfc-as-custom-element}
175189

176190
`defineCustomElement` also works with Vue Single-File Components (SFCs). However, with the default tooling setup, the `<style>` inside the SFCs will still be extracted and merged into a single CSS file during production build. When using an SFC as a custom element, it is often desirable to inject the `<style>` tags into the custom element's shadow root instead.
@@ -242,7 +256,7 @@ export const Counter = defineCustomElement(CounterSFC)
242256
// register global typings
243257
declare module 'vue' {
244258
export interface GlobalComponents {
245-
'Counter': typeof Counter,
259+
Counter: typeof Counter
246260
}
247261
}
248262
```

0 commit comments

Comments
 (0)