Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

$el of templateRef points to comment VNode instead of first real child of component #12680

Open
markbrockhoff opened this issue Jan 10, 2025 · 3 comments

Comments

@markbrockhoff
Copy link

Vue version

3.5.15

Link to minimal reproduction

https://play.vuejs.org/#__PROD__eNp9U9uO2jAQ/ZWpVWlBAqOK9oUCUot4aNWbKI+WqigZghfHjnzJIiH+vWPnUrqs9i32nHN8Zs7kwj7VNW8CsgVbutzK2oPKdLkSzDvBwKEP9VpoWdXGetgcpSrgYE0FD3yWTpH88HFAXCA43GNVq8zjDg8TMPq7CdpjAdeO2TGEzo12HvIoQ1BYPeOOBEs1wcYEH3RGozGs1nARGiAqGIVcmbJHRyVUWKH2C8EmgzxvMhWQv0UV1Yh6d8+zotg2xPsmnUeNNkoqmZ+izM2jz5/dRAz1t0fnW68A17HQ1/i5nLVjpSHSwXfd0QlgWcgGcpU5R+OuM0svC5YqVGtHbfFAtW4KMGtpM+KtAaL2jR6bUGRk7CBL/uiMpkSTW6KbqpYK7c/aSzIu2KLvQ7BMKfP0Nd15G3DS3+dHzE8v3D+6c7wT7JdFh7ZBmk1f85ktkVqI5e3vH3im76FYmSIoQr9S3CENNUSPLexz0AXZvsElt1/Spkld7t32TDm5vqloNM0+4QWjPdu80vo/u3P+PvEoMprisNbxn/g/sDfTKeywMg2CP0pHe1DFPQNvoMpOSGHSJpAzWnp6oN0HeDL2BNPpfeRdrF3iCT3Eex/unwZtbJVczfkH/m7Orn8BgY08Yw==

Steps to reproduce

Hi, I just spent some hours debugging a very strange behavior when accessing the underlying element of a component ref by using templateRef.$el. The component I placed the template ref on had only one root level <div> inside its template, however there was a comment above it. It looks like this leads to the element being referenced by the template ref being the VNode of this comment instead of the <div> element.

Steps to reproduce:

  1. Open the Playground
  2. Open the console and see that the element referenced by childRef.value.$el is a text VNode
  3. Click on the text "Test" in the preview (Nothing should be logged to the console)
  4. Go into the component "Child.vue" and remove the comment in line 2
  5. After a hot reload (or manual one) childRef.value.$el should point to the div element as logged to the console. Clicking on the text "Test" in the preview should now also log "Clicked Test" to the console

What is expected?

I would expect templateRef.$el to point to the first real element inside the component excluding comments.

What is actually happening?

templateRef.$el points to a VNode for the comment inside the components template.

System Info

No response

Any additional comments?

No response

@xfontr
Copy link

xfontr commented Jan 11, 2025

Hey! Not working on the open source (not yet!) but hopefully can provide some insight on the topic, as I do develop in Vue.

Your Child component has two nodes, one HTMLDivElement and one of type Comment.

Vue will get the actual node if you are pointing to a html node or a Vue component that has only one child.

Therefore, this has nothing to do with the comment. You are asking Vue to add an event listener to a Vue Component that doesn't have a clear single valid node. Vue is not pointing to the Comment VNode, as you are suggesting.

It doesn't know where do you expect to assign the event listener. So, IMHO, this is expected behaviour.

Ways to fix this:

Solution 1 Wrap both components within a HTML node, such as another div.

Solution 2 Add a ref in the child's node where you want the addEventListener placed, in this case the div. You can later access that from the Parent component using childRef.value.$refs.yourRefName

Having said all that, though... From a dev's POV I would agree that it would make more sense if the comment was simply ignored.

@edison1105 edison1105 added 🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. 🔩 p2-edge-case and removed 🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. 🔩 p2-edge-case labels Jan 12, 2025
@edison1105
Copy link
Member

The root VNode of Child.vue is a Fragment. the text node is the Fragment's anchor.

@markbrockhoff
Copy link
Author

Having said all that, though... From a dev's POV I would agree that it would make more sense if the comment was simply ignored.

Exactly, if there were two actual element inside the root of the template I'd totally agree and expect the issue. However having Vue respect a comment as part of the Fragment feels unintuitive.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants