Subscribe on changes!

missing instance information for directives in beforeMount hook when using setup syntax

avatar
Sep 28th 2022

Vue version

3.2.39

Link to minimal reproduction

https://stackblitz.com/edit/vitejs-vite-zmkeex?file=src/main.js

Steps to reproduce

  • create a directive in main.js
  • create a component with the following properties:
    • use the setup syntax
    • create a function (empty script tag doesn't cause problems)
    • in the template call the directive

What is expected?

in the beforeMount function, the options should have an instance property which has the information of the component which calls the directive.

What is actually happening?

the instance property contains an empty Proxy object

System Info

No response

Any additional comments?

In the stackblitz example I created a ComponentA.vue (setup syntax) and a ComponentB.vue to see how the instance property differs when the beforeMounted hook is called in both cases. The result is console logged.

avatar
Sep 28th 2022

You need to use defineExpose() (which you do) to define properties that are available as properties on the instance object. Those will be exposed through the proxy you see logged to the console. you can verify that by loggingoptions.instance.myFunc.

avatar
Sep 28th 2022

You need to use defineExpose() (which you do) to define properties that are available as properties on the instance object. Those will be exposed through the proxy you see logged to the console. you can verify that by loggingoptions.instance.myFunc.

thanks for the tipp. That way quite a nasty bug on my side to hunt down. defineExpose() did the trick indeed 👍 .

avatar
Sep 28th 2022

out of curiosity, is the need for defineExpose intended or a limitation of the script setup syntax?

avatar
Sep 28th 2022

script setup instances are intentionally closed by default. no instance state is exposed to the outside unless it's explicitly mean to be.

This is a learning we had: When any property you use in your component can implicitly become part of its API consumed by other parts of the app through template refs or custom directives, you can easily break things by doing something as simple as refactoring a function in your component, or renaming a piece of state.

So when we designed script setup, we made it part of the "spec" that we make them "closed" by default and leave it to developers to explicitly define the APIs they want to expose with defineExpose().

The expose feature is available on normal components as well, but for reasons it backwards compat, normal components are open by default until the dev explicictly exoses something

avatar
Sep 28th 2022

got it, thank you 😄