feat(custom-element): useHost() helper

This commit is contained in:
Evan You 2024-08-08 12:35:00 +08:00
parent e044b6e737
commit 775103af37
No known key found for this signature in database
GPG Key ID: 00E9AB7A6704CE0A
3 changed files with 36 additions and 13 deletions

View File

@ -14,6 +14,7 @@ import {
ref, ref,
render, render,
renderSlot, renderSlot,
useHost,
useShadowRoot, useShadowRoot,
} from '../src' } from '../src'
@ -975,8 +976,22 @@ describe('defineCustomElement', () => {
}) })
}) })
describe('useShadowRoot', () => { describe('helpers', () => {
test('should work for style injection', () => { test('useHost', () => {
const Foo = defineCustomElement({
setup() {
const host = useHost()!
host.setAttribute('id', 'host')
return () => h('div', 'hello')
},
})
customElements.define('my-el-use-host', Foo)
container.innerHTML = `<my-el-use-host>`
const el = container.childNodes[0] as VueElement
expect(el.id).toBe('host')
})
test('useShadowRoot for style injection', () => {
const Foo = defineCustomElement({ const Foo = defineCustomElement({
setup() { setup() {
const root = useShadowRoot()! const root = useShadowRoot()!
@ -986,8 +1001,8 @@ describe('defineCustomElement', () => {
return () => h('div', 'hello') return () => h('div', 'hello')
}, },
}) })
customElements.define('my-el', Foo) customElements.define('my-el-use-shadow-root', Foo)
container.innerHTML = `<my-el></my-el>` container.innerHTML = `<my-el-use-shadow-root>`
const el = container.childNodes[0] as VueElement const el = container.childNodes[0] as VueElement
const style = el.shadowRoot?.querySelector('style')! const style = el.shadowRoot?.querySelector('style')!
expect(style.textContent).toBe(`div { color: red; }`) expect(style.textContent).toBe(`div { color: red; }`)

View File

@ -653,24 +653,31 @@ export class VueElement
} }
} }
/** export function useHost(caller?: string): VueElement | null {
* Retrieve the shadowRoot of the current custom element. Only usable in setup()
* of a `defineCustomElement` component.
*/
export function useShadowRoot(): ShadowRoot | null {
const instance = getCurrentInstance() const instance = getCurrentInstance()
const el = instance && instance.ce const el = instance && (instance.ce as VueElement)
if (el) { if (el) {
return (el as VueElement).shadowRoot return el
} else if (__DEV__) { } else if (__DEV__) {
if (!instance) { if (!instance) {
warn(`useShadowRoot called without an active component instance.`) warn(
`${caller || 'useHost'} called without an active component instance.`,
)
} else { } else {
warn( warn(
`useShadowRoot can only be used in components defined via ` + `${caller || 'useHost'} can only be used in components defined via ` +
`defineCustomElement.`, `defineCustomElement.`,
) )
} }
} }
return null return null
} }
/**
* Retrieve the shadowRoot of the current custom element. Only usable in setup()
* of a `defineCustomElement` component.
*/
export function useShadowRoot(): ShadowRoot | null {
const el = __DEV__ ? useHost('useShadowRoot') : useHost()
return el && el.shadowRoot
}

View File

@ -247,6 +247,7 @@ export {
defineCustomElement, defineCustomElement,
defineSSRCustomElement, defineSSRCustomElement,
useShadowRoot, useShadowRoot,
useHost,
VueElement, VueElement,
type VueElementConstructor, type VueElementConstructor,
type CustomElementOptions, type CustomElementOptions,