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

View File

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