Subscribe on changes!

Replace $el and $refs with methods. Without $el and $refs accessing the DOM in Vue 3 get's much harder

avatar
Jun 1st 2021

What problem does this feature solve?

I have posted the following message in Quasar framework discussion board and thought of bringing it here for discussion as well as this is relevant for any Vue 3 application and especially relevant for ui frameworks

Since template refs are now declarative only, there is no standard way of accessing at the minimum, root elements.

My Post from https://github.com/quasarframework/quasar/discussions/9500:

Point for thought, now that this.$el and this.$refs are deprecated or removed from Vue 3, accessing the DOM get's much harder

Take for example very simple situations where you'd want to access the DOM of QPage to attach events programmatically, or maybe you want to focus on QBtn after an action or want to set the caret inside a QInput as discussed and solved specifically here

In Vue 2, this was a relatively easy task,

If I wanted to measure the width and height of QCard I could easily do this.$refs.myCard.$el.clientHeight or even the riskier this.$refs.myQInput.$refs.input to access native input element

There are many reasons we'd need access to the DOM and I certainly don't expect QBtn to implement focus() method or any other specific solutions

This is a problem with whole Vue 3 IMO and not specific to Quasar, but might be preemptively solved or discussed here

So my general direction for solution for this was having all or most components expose getRootElement() method systematically and others should also have getNativeElement() if relevant. This could relatively easily be implemented with shared composables, but the template ref part would still need to be implemented in all components individually

The only oversight I currently think of for this, and the reason this.$el was removed from Vue 3, is that components can now have more then 1 root element. Not sure of best way to solve this systematically but simplest solution would be to simply return an array of refs for getRootElement(). Maybe it should always return array for consistency

I would love to hear thoughts on this as I mulled over it for some time. I truly think this might have been an oversight on the Vue's team front

What does the proposed API look like?

So my general direction for solution for this was having all or most components expose getRootElement() method systematically and others should also have getNativeElement() if relevant. This could relatively easily be implemented with shared composables, but the template ref part would still need to be implemented in all components individually

The only oversight I currently think of for this, and the reason this.$el was removed from Vue 3, is that components can now have more then 1 root element. Not sure of best way to solve this systematically but simplest solution would be to simply return an array of refs for getRootElement(). Maybe it should always return array for consistency

avatar
Jun 1st 2021

Point for thought, now that this.$el and this.$refs are deprecated or removed from Vue 3, accessing the DOM get's much harder

I don't know what you are referring to here.

Both properties still exist and neither have been deprecated. In composition API, you can use template refs to the same effect.

If you want to discuss or propose a change/addition to Vue's features, please use the RFC process. That repo also has an open discussion board more suited for this type of "I wanna hear your thoughts" issue.

https://github.com/vuejs/rfcs/discussions

avatar
Jun 2nd 2021

@LinusBorg

In composition API, you can use template refs to the same effect.

If we're talking about composition api's only (let's for Vue 4 where options api is removed completely theoretically) Would $el still be relavent? Are declared refs in composition api go to $refs object?

i.e.

<q-card ref="myCard"></q-card>
...
setup() {
const myCard = ref(null)

function attachNativeDOMEvents() {
    myCard.value.{one of cards native DOM element?}.addEventListener(...)
}

return {myRef}
}

would you access myCard.value.$refs.cardContainer if card used a composition template ref to register its container (which of course is dangerous by itself but sometimes unavoidable)? if it's using fragments and you want to calculate width and height or set scroll position, would you do myCard.value.$el.scrollTop? that is, if card is also using composition inside it, or moreover, since it's from a third party library, you can't rely on card insides. Would each library have to solve this periodically for it self creating many different standards?

avatar
Jun 2nd 2021

let's for Vue 4 where options api is removed completely theoretically

Just to be clear: That won't happen. The Options API is not and will not be deprecated.

Further discussion can happen in the RFC discussion topic that you opened.