Vue: Consistency in `$refs`: all children of $refs array using same format.

Created on 17 Jul 2019  Â·  1Comment  Â·  Source: vuejs/vue

What problem does this feature solve?

I know this is intended as a feature, but I encountered a lot of issues when trying to access $refs due to all the different formats:

  • If ref is inside a v-for, the $refs element will be an array. This wouldn't be necessary since is trivial to add an unique name to the ref inside a loop, as seen in this example
  • If ref is outside of a v-for, it will be a DOM Node.
  • Except that when the referenced item is a custom component, then it will be an object and to access the DOM node you would have to read the $el property...

So basically, if we wanted to select a ref's node, and we wouldn't know if it's a node or a custom component, if it's in a for-loop or not, this would be the code:

const ref = (this.$refs.test && this.$refs.test[0] && this.$refs.test[0].$el) ? this.$refs.test[0].$el
    : (this.$refs.test && this.$refs.test.$el) ? this.$refs.test.$el
    : (this.$refs.test && this.$refs.test[0]) ? this.$refs.test[0]
    : this.$refs.test ? this.$refs.test
    : null;`

So far I've never encountered this case, but I did encounter:

  • The case where the ref could be either a node or a custom component — I wanted to add a class and remove it with a timeout, for animation purposes. At the end, my workaround was to create a custom component to handle the "empty state" of a component, to consistently be able to reference the node using .$el (this was easier than refactoring all the parts where .$el was being referenced)-
  • The case where the ref could either be a node or an array of nodes, in a case of a list that had a default value (the default value was outside of the "for loop").

My proposal is to have a consistent way of referencing a node/component inside templates.

An idea I found in another issue of this repo is to use a special syntax when the ref is expected to be an array:

<div ref:multiple="example"></div>

Another part of the proposed change is to be able to access the DOM Node using $el (__always__ and exclusively that way).

Since this is a breaking change, it would be interesting to hear workarounds for this. For example, using a different keyword altogether.

In general, I think this would add a lot of sanity and consistency to the usage of $refs, and I think it's a common issue for a lot of beginners.

Note: this feature request is not compatible with this other feature request

What does the proposed API look like?

<!-- Refs inside loops: -->
<div v-for="...">
    <div ref:multiple="example"></div>
    (or ref:nested="example")
</div>
// Refs array
[
    0: { $el: <div></div> }, // simple node item
    1: { $el: <div></div>, methods, data, etc..... }, // ref in custom component
    ...
}
discussion

Most helpful comment

Reworking refs as a breaking change should go through an RFC as it needs a deeper consideration of what is breaking.

To me the problem you are facing isn't clear and I'm not sure if it's a documentation problem instead. Some of the issues you are referencing are too old and now outdated in term of initial problem and comments, so let's keep this open as a discussion for the moment

Regarding many of your points, I wanted to clarify on some of those:

f ref is inside a v-for, the $refs element will be an array. This wouldn't be necessary since is trivial to add an unique name to the ref inside a loop, as seen in this example

It's not the same, as having an array allows you to iterate through it, while having variable names with indexes attached to it doesn't if one of them is skipped with a v-if or other

If ref is outside of a v-for, it will be a DOM Node.

Or a component

That example is quite misleading, such complexity would only exist in a case where all posibilities for ref exist in the same template. In which scenario the template itself would be a bigger problem probably

The case where the ref could be either a node or a custom component

That is a feature, limiting refs to just elements would not allow calling methods on the component and other patterns

The case where the ref could either be a node or an array of nodes, in a case of a list that had a default value (the default value was outside of the "for loop").

In that case there must be some conditional switching between the v-for + ref version and the regular ref, that same conditional could be used to know if ref should be treated as an array or as a single element (from a business-logic perspective). Most of the cases the handling is similar and using an Array.isArray check is enough

>All comments

Reworking refs as a breaking change should go through an RFC as it needs a deeper consideration of what is breaking.

To me the problem you are facing isn't clear and I'm not sure if it's a documentation problem instead. Some of the issues you are referencing are too old and now outdated in term of initial problem and comments, so let's keep this open as a discussion for the moment

Regarding many of your points, I wanted to clarify on some of those:

f ref is inside a v-for, the $refs element will be an array. This wouldn't be necessary since is trivial to add an unique name to the ref inside a loop, as seen in this example

It's not the same, as having an array allows you to iterate through it, while having variable names with indexes attached to it doesn't if one of them is skipped with a v-if or other

If ref is outside of a v-for, it will be a DOM Node.

Or a component

That example is quite misleading, such complexity would only exist in a case where all posibilities for ref exist in the same template. In which scenario the template itself would be a bigger problem probably

The case where the ref could be either a node or a custom component

That is a feature, limiting refs to just elements would not allow calling methods on the component and other patterns

The case where the ref could either be a node or an array of nodes, in a case of a list that had a default value (the default value was outside of the "for loop").

In that case there must be some conditional switching between the v-for + ref version and the regular ref, that same conditional could be used to know if ref should be treated as an array or as a single element (from a business-logic perspective). Most of the cases the handling is similar and using an Array.isArray check is enough

Was this page helpful?
0 / 5 - 0 ratings

Related issues

robertleeplummerjr picture robertleeplummerjr  Â·  3Comments

bdedardel picture bdedardel  Â·  3Comments

seemsindie picture seemsindie  Â·  3Comments

aviggngyv picture aviggngyv  Â·  3Comments

fergaldoyle picture fergaldoyle  Â·  3Comments