Expose method creating a web-component using Vue3
Asked Answered
G

1

6

I am creating a web-component using VueJS 3, I want to expose a method on the component allowing the user to do something like this:

  <custom-component id="x1" />

  <script>
    var component = document.getElementById("x1");
    
    component.customMethod(); // as focus() method on native elements
  </script>

If I define a method on the component, I can call the method inside the component. But the method is not available when I use it as a web-component.

  //main.ts/js
  import { defineCustomElement } from "vue"
  import component from "./component.ce.vue"

  const element = defineCustomElement(component );

  customElements.define("custom-component ", element);
  //component.ce.vue
  const customMethod = () => { console.log("Executed"); }

How I can indicate to Vue Component Wrapper that the customMethod will be available outside the component?

Gape answered 20/2, 2022 at 19:56 Comment(0)
B
10

In <script setup>, use the defineExpose() macro:

<script setup>
const customMethod = () => {β‹―}
      πŸ‘‡
defineExpose({ customMethod })
</script>

In the setup() hook, use the expose property of the context argument:

<script>
export default {   πŸ‘‡
  setup(props, { expose }) {
    const customMethod = () => {β‹―}
      πŸ‘‡
    expose({ customMethod })
  }
}
</script>

In the Options API, use the expose option:

<script>
export default {
     πŸ‘‡
  expose: ['customMethod'],
  methods: {
    customMethod() {β‹―}
  }
}
</script>

Currently (as of Vue 3.2.31), the only way to access the custom element's exposed properties is through its _instance.exposed property:

<!-- example/index.html -->
<body>
  <custom-component id="x1"></custom-component>
  <script>
    const el = document.getElementById('x1')
                   πŸ‘‡
    el._instance.exposed.customMethod()
  </script>
</body>

Since _instance is a private property, use this solution with caution, as the property could be renamed/removed in a future release.

demo (<script setup>)

demo (setup() hook)

demo (Options API)

Belemnite answered 21/2, 2022 at 20:54 Comment(1)
As of 3.3.7, accessing _instance in a component defined with a .ce.vue file that has defineExpose({ .. }) doesn't work and the methods are not available for calling. -1 for this answer. There is a bug report considered to be a feature request, which is a clear regression from 2.x (github.com/vuejs/core/issues/5540) that is over a year old and nobody is looking into solving the problem. – Inunction

© 2022 - 2024 β€” McMap. All rights reserved.