You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
This is not primarily about
useTemplateRef()ergonomics.The core issue is that Vue currently uses the same template-ref mechanism for two different concepts:
In Vue 3, especially with
<script setup>anddefineExpose(), these two concepts are increasingly distinct.Problem
A component ref is naturally the component's public API:
<MyDialog ref="dialog" />But a parent may also need the component's rendered DOM element for:
For example:
<MyButton ref="button" />If
MyButtonusesdefineExpose():the parent receives the exposed component API, not a DOM element.
To expose the actual
<button>, the child currently has to make an internal template ref part of its public API:This mixes two unrelated concerns:
Proposal
Introduce a separate first-class concept for the rendered element of a component.
The exact syntax is not important. For example:
<MyButton ref="button" element-ref="buttonEl" />Then:
could mean:
Another possible API could be:
or:
The important part is the semantic separation, not the exact API.
Root Resolution
I think element refs could follow rules similar to Vue's existing fallthrough attribute behavior.
Single native root
The element ref resolves to:
HTMLButtonElementSingle component root
The element ref could follow the unambiguous root chain and resolve to the
<button>.This is conceptually similar to how fallthrough attributes can pass through a component root.
Multiple roots
There is no unambiguous rendered root.
Vue could:
null;This is already a familiar concept in Vue because multiple-root components require explicit handling for fallthrough attributes.
Why this matters more in Vue 3
defineExpose()gives components an explicit public interface.For example:
That API should not need to include an internal DOM ref simply because the parent wants to measure or observe the rendered element.
Conceptually:
These are independent capabilities.
Relationship to
useTemplateRef()useTemplateRef()improves how template refs are accessed:instead of relying on a variable with the same name:
But it preserves the existing underlying semantics:
So
useTemplateRef()improves ergonomics, but does not address the distinction described here.Benefits
A separate rendered-element ref would:
defineExpose()focused on the component's actual public API;It may also become more useful as Vue evolves rendering modes where component public refs do not necessarily expose
$el.Summary
Vue currently treats these two operations as one template-ref concept:
I think they should be separate first-class concepts.
A reasonable model could be:
with root resolution rules similar to fallthrough attributes:
This would improve encapsulation while making DOM interoperability easier without overloading the component public API.
All reactions