This commit is contained in:
edison 2025-06-19 09:53:21 +08:00 committed by GitHub
commit b4d0d24b2e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 46 additions and 0 deletions

View File

@ -17,6 +17,7 @@ import {
render,
renderSlot,
useHost,
useHostInternals,
useShadowRoot,
} from '../src'
@ -1399,6 +1400,21 @@ describe('defineCustomElement', () => {
const style = el.shadowRoot?.querySelector('style')!
expect(style.textContent).toBe(`div { color: red; }`)
})
// wait for jsdom to fix https://github.com/jsdom/jsdom/issues/3732
test.todo('useHostInternals', async () => {
const Foo = defineCustomElement({
setup() {
const internals = useHostInternals()!
internals.ariaLive = 'polite'
return () => h('div', 'hello')
},
})
customElements.define('my-el-use-host-internals', Foo)
container.innerHTML = `<my-el-use-host-internals>`
const el = container.childNodes[0] as VueElement
expect(el._internals?.ariaLive).toBe('polite')
})
})
describe('expose', () => {
@ -1712,6 +1728,20 @@ describe('defineCustomElement', () => {
expect(e.shadowRoot!.innerHTML).toBe(`false,boolean`)
})
test('support attachInternals method', () => {
const E = defineCustomElement({
formAssociated: true,
render() {
return h('div', 'hello')
},
})
customElements.define('my-el-attach-internals', E)
container.innerHTML = `<my-el-attach-internals></my-el-attach-internals>`
const e = container.childNodes[0] as VueElement
expect(e.shadowRoot!.innerHTML).toBe(`<div>hello</div>`)
expect(e._internals).toBeTruthy()
})
test('hyphenated attr removal', async () => {
const E = defineCustomElement({
props: {

View File

@ -176,6 +176,8 @@ export function defineCustomElement(
if (isPlainObject(Comp)) extend(Comp, extraOptions)
class VueCustomElement extends VueElement {
static def = Comp
static formAssociated = !!options.formAssociated
constructor(initialProps?: Record<string, any>) {
super(Comp, initialProps, _createApp)
}
@ -204,6 +206,7 @@ export class VueElement
implements ComponentCustomElementInterface
{
_isVueCE = true
_internals: ElementInternals | null = null
/**
* @internal
*/
@ -253,6 +256,9 @@ export class VueElement
private _createApp: CreateAppFunction<Element> = createApp,
) {
super()
if (this.attachInternals) this._internals = this.attachInternals()
if (this.shadowRoot && _createApp !== createApp) {
this._root = this.shadowRoot
} else {
@ -716,3 +722,12 @@ export function useShadowRoot(): ShadowRoot | null {
const el = __DEV__ ? useHost('useShadowRoot') : useHost()
return el && el.shadowRoot
}
/**
* Retrieve the ElementInternals of the current custom element. Only usable in setup()
* of a `defineCustomElement` component.
*/
export function useHostInternals(): ElementInternals | null {
const el = __DEV__ ? useHost('useHostInternals') : useHost()
return el && el._internals
}

View File

@ -256,6 +256,7 @@ export {
defineSSRCustomElement,
useShadowRoot,
useHost,
useHostInternals,
VueElement,
type VueElementConstructor,
type CustomElementOptions,