Skip to content

Properties in defineExpose are undefined if component doesn't have a template ref on it #2107

@markbrockhoff

Description

@markbrockhoff

Subject of the issue

Hi, I just encountered a really strange issue while trying to access the vm of a component inside my test.
In the end all I did was to call .getComponent(Component).vm.exposedFunction() however I ended up with an error saying that exposedFunction was undefined. I investigated a bit and found out the following things:

  1. Accessing the exposed function via .getCurrentComponent() works, e.g.: .getComponent(Component).getCurrentComponent().exposed?.exposedFunction()
  2. Logging out the result of .getComponent(Component).vm shows all normal values and props of the component but none of the things inside defineExpose()
  3. Placing a ref on the component makes it work. Since within this usage of the component none of the exposed functions was used there was no template ref on it. Adding one like ref="someRef" magically made the properties from defineExpose() available on the vm.

Steps to reproduce

Use a component with a exposed function within an other one, e.g.:

<!-- Child.vue -->
<script setup>
defineExpose({
  exposedFunction: () => {},
});
</script>

<template>
  <div>Hello World</div>
</template>
<!-- Parent.vue -->
<template>
  <div>
    <Child />
  </div>
</template>

Now try to access the vm of the Child component from within a test:

it("calls the exposed function", () => {
  const wrapper = mount(Parent);

  // wrapper.getComponent(Child).getCurrentComponent.exposed?.exposedFunction();
  //                                                      ^ Calling the exposed function like this works

  wrapper.getComponent(Child).vm.exposedFunction();
  //                                                        ^ This will be undefined, so calling it will throw an error
})

Try adding a ref to the child component e.g.:

<Parent>
  <Child ref="child" />
</Parent>

The test will no longer throw and the exposed function is executed.

Expected behaviour

Properties / functions exposed using defineExpose() should always be available on the vm, even if the component doesn't have a template ref on it.

Actual behaviour

Properties / functions of defineExpose() are only available on the vm if the component instance has a ref on it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions