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

Directives do not work on <RouterLink custom> #2375

Open
decademoon opened this issue Sep 29, 2024 · 1 comment
Open

Directives do not work on <RouterLink custom> #2375

decademoon opened this issue Sep 29, 2024 · 1 comment
Labels
enhancement New feature or request

Comments

@decademoon
Copy link

Reproduction

https://play.vuejs.org/#eNqVVNtu2zAM/RXBG+AUaKxdij4YSZB1K9YNu6Ebtod5D47NJGpkyZDoJEWQfx8lJY7TdRn2kAvJw8NDitImqnKhkjsbpZGoam2QbVhhIEd4Vddsy6ZGVyxeNhBnqgUY3SCYNprw4DhAXO4+ltd1EvIz1TL36HOWKcaSxkIvpAe70o3CXvyE0uKz6DzapZO+gS2MqJFZwKYetbU+CLV4q3XZFtw7dlU7sKv8GEX2DlRoZZEtr7Qs2ZCBZMMRfScW7yUkU63wB4jZHCkWTwhDGQMe5JAQMhCqWlJrZDE2aCWhHmYRzyK27Ls05vnIVWipTcoMlFk0eiMMFCiWwFbaLOygbSCQTcyB1DXwn5ylBqti9NyBmkiIccBbzTTlcAIJPrIHH6HS5v5GWKSf853z9ngDaIj9dgfakd/oCr4LWLUz3zvafYC1B4bp77ZqeFSit3HNz0P19DFJvbNzB/HZNmU/ncFIfZ3jPGUxj0mzJkEKFKYHTVuf9Yu+t7R4NIKuuIfbxmSuZjRjtDTb02c/fzHaMw04GQ8nHWbTr/Kabp1WVMl3mO0CVCBl3uN8h7k6dxbNEWubct6oejFLqC1+QIwvkpfJM17SVDreBGzVnxi9svT/jth92457TCBewhK1lraf1+JvJf4Aji+Ty+Q5l2LCiZ0LVcLaczvqLQ2U2kRLhzoVswdNupMQEsznGgUd+lGzuZR69d770DTQCi3mUCwe8d/ZdZD8xQB1t4ROc5ibGWAIX3/9BGv63wYrXTaS0CeCt2C1bJzGALtqVEmyOziv9p0/M6Fm3+z1GkHZfVNOqJ+Gx/uDfH2i9YPcl8lFZ4rdp8zt5PGqhRviMN4mj5UaeQjyo2hnB/2yd16/U7ysaOiOVfTUOGa6ABs2NzA9ZypfihklkFB3IXzxnKUuSCj3Qw/UuJCiWJC9R4dHi/aFfE9zRBOuk8s+Eu/k5/9uY/sbfE5I2w==

Steps to reproduce the bug

Click the reproduction link.

Expected behavior

The second link should be bold.

Actual behavior

The second link is not bold.

Additional information

I understand why this happens. Vue 3 does not support custom directives on components that render multiple root nodes. This is also the case if the render function returns an array of a single vnode since it'll get converted into a fragment.

Screenshot 2024-09-29 at 11 23 22 am

This is the RouterLink render function:

return () => {
const children = slots.default && slots.default(link)
return props.custom
? children
: h(
'a',
{
'aria-current': link.isExactActive
? props.ariaCurrentValue
: null,
href: link.href,
// this would override user added attrs but Vue will still add
// the listener, so we end up triggering both
onClick: link.navigate,
class: elClass.value,
},
children
)
}

If custom is false then a single <a> element is the root element of the component and everything works as expected.

If custom is true then the result of calling the default slot function is returned instead. The vue template compiler will wrap the default slot in an array even if it only contains a single node, so it will become a fragment.

The only fix I can think of is to change the RouterLink render function so that the result of the default slot is unwrapped if it is an array of length 1:

function preferSingleVNode(vnodes) {
  return Array.isArray(vnodes) && vnodes.length === 1 ? vnodes[0] : vnodes;
}
const children = preferSingleVNode(slots.default && slots.default(link))

It's really unfortunate that Vue 3 cannot do something that Vue 2 was able to do: vuejs/core#3914

@posva
Copy link
Member

posva commented Sep 29, 2024

The fix seems very reasonable. PR welcome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants