Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue 3 Composition API - How to get the component element ($el) on which component is mounted

Tags:

I want to use onMounted to initiate third-party library. To do that I need the component element as its context. In Vue 2 I would get it with this.$el but not sure how to do it with composition functions. setup has two arguments and none of them contains the element.

setup(props, context) {     onMounted(() => {         interact($el)             .resizable();     }) } 
like image 248
Damir Miladinov Avatar asked May 04 '20 19:05

Damir Miladinov


People also ask

How do I show components on click Vue?

Simply use @click (v-on:click) to toggle Bool. The v-model simply means that it doesn't show if it's false and it does if it's true.

How do I reference an element in Vue?

Referencing DOM Elements in Vue # If we want to reference a DOM element, we can use the ref attribute in Vue. Vue can store references to DOM elements in a property called $ref . The first thing we have to do, is add a ref attribute to the element we want to reference in our Javascript.

What is $El in VueJS?

The $el option in Vue provides Vue with an existing HTML element to mount the Vue instance generated using the new keyword. this. $el. querySelector is used to access HTML elements and modify the element's properties. this.


2 Answers

tl;dr:

In Vue 3, components are no longer limited at only 1 root element. Implicitly, this means you no longer have an $el.
You have to use ref to interact with any element in your template.

As pointed out by @AndrewSee in comments, when using a render function (not a template), you can specify the desired ref in createElement options:

render: function (createElement) {   return createElement('div', { ref: 'root' }) } // or, in short form: render: h => h('div', { ref: 'root' }) 

initial answer:

As outlined in docs,

[...] the concepts of reactive refs and template refs are unified in Vue 3.

And you also have an example on how to ref a "root" element. Obviously, you don't need to name it root. Name it $el, if you prefer. However, doing so doesn't mean it will be available as this.$el, but as this.$refs.$el.

<template>   <div ref="root"></div> </template>  <script>   import { ref, onMounted } from 'vue'    export default {     setup() {       const root = ref(null)        onMounted(() => {         // the DOM element will be assigned to the ref after initial render         console.log(root.value) // this is your $el       })        return {         root       }     }   } </script> 

In Vue 3 you're no longer limited to only one root element in <template>, so you have to specifically reference any element you want to interact with.

like image 185
tao Avatar answered Sep 19 '22 14:09

tao


In Vue 3 + Composition API there is no $el alternative provided.

Even if you use Vue 3 with Options API, due to the availability of Fragments, it is recommended to use template refs for direct access to DOM nodes instead of relying on this.$el.


How to initiate a third-part-library

Let's say we have a div element for the third-part-library:

<template>   Below we have a third-party-lib   <div class="third-party-lib"></div> </template> 

And then we want to initiate it from the Javascript:

Solution 1 (recommended): Using template refs

<script setup> import { ref, onMounted } from 'vue';  const $thirdPartyLib = ref(null); // template ref  onMounted(() => {   $thirdPartyLib.value.innerText = 'Dynamically loaded'; }); </script>  <template>   Below we have a third-party-lib   <div ref="$thirdPartyLib" class="third-party-lib"></div> </template> 

Solution 2 (not recommended): Using non-documented @VnodeMounted

<script setup> function initLib({ el }) {   el.innerText = 'Dynamic content'; } </script>  <template>   Below we have a third-party-lib   <div class="third-party-lib" @VnodeMounted="initLib"></div> </template> 

See both solutions live

like image 21
Roland Avatar answered Sep 19 '22 14:09

Roland