core icon indicating copy to clipboard operation
core copied to clipboard

Edge Case: Directives in v-if with specific key (1) will not trigger mounted hook in v-else case with a diffrent Directive.

Open benjamin-larsen opened this issue 3 months ago • 5 comments

Vue version

latest

Link to minimal reproduction

https://play.vuejs.org/#eNqlUk1PwzAM/SsmFzZpa8XgVHUVH9oBDoBgx1y21i3Z0qTKRxma9t9xWzqKNO2CVFWx37Pznp09u6uqoPbIIhbb1IjKgUXnq4QrUVbaONiDwRwOkBtdwiVRL7niKtXKOqiXSP857LkCKLVXDrMIRignsBYqE6oYwzzpYACUgVAKzRJ3TRFnbTlnDXrgir4/fWf/bDw71dnpopBIJDI1csbjmKs47JyTZwoclpVcOaQIIM5EDfVU5HPOulLOINriF8VXdKynjm5K4pB4wwKUFn/A2RBde+e0gttUinR77ElyLvruSXeIw45KZXE4kMQmzFmykosi2FitaG/tEDhLdVkJiealcoKschb14+FsJaX+fGpzjedJn08/MN2eyG/srslx9mrQoqlJ1xFzK1Mgba2BF+/PNPIBWOrMNy7OgG9otfSNxo5271VGsge8Vu1j+/po0Uu72DlUtjfVCG332vJp1x4fzlj/lXsd3PTvgR2+AVtl/MY=

Steps to reproduce

Make a Directive (referred to as "Test Directive 1") with mounted hook that sets innerText of element to a unique value different that Test Directive 2. Then make another Directive (referred to as "Test Directive 2") with simmilar mounted hook that sets innerText of element to another value.

Make a toggle ref, and a button to change the toggle, then make a v-if where the key is the number 1 with Test Directive 1, and v-else with no key, with Test Directive 2.

Then click the toggle button, and you'll see that innerText is not changed, hence the other Test Directive's mounted hook was not called.

What is expected?

What should be expected is that the v-else is a diffrent element meaning directives should run mounted hook again, but instead it does nothing.

What is actually happening?

Keys: The Vue Compiler generates keys for v-if/v-else, but it does not check for conflicts, in this case we set key to Number 1, which the Vue Compiler uses for v-else.

Directives: Vue runs invokeDirectiveHook for mounted hook when the element is mounted, not when the Directive is "mounted".

System Info


Any additional comments?

You can make keys generated by vue compiler symbols, or check for conflicts (might be more difficult to do at compile time tho especially with dynamic keys).

You can run mounted hook and and destroyed hook when the directive itself is added or removed (and keeping of course the current when element is mounted/unmounted.)

benjamin-larsen avatar Sep 13 '25 21:09 benjamin-larsen

By latest, I mean the latest of the Vue Playground, locally I used version 3.5.18.

benjamin-larsen avatar Sep 13 '25 21:09 benjamin-larsen

v-if and v-else automatically generate a key. By adding :key="1" to v-if, both v-if and v-else end up with the same key of 1, which affects the patch logic.

edison1105 avatar Sep 15 '25 02:09 edison1105

It's also important to note, this may happen with v-for lists where index is used with atleast 2 items too. So simply checking the Number Literal as key may not be the solution.

benjamin-larsen avatar Sep 15 '25 08:09 benjamin-larsen

https://play.vuejs.org/#eNp9UctOwzAQ/JXFl4JUGhU4VWnEQz3AARBw9KWkm+DWsS17E4qq/DvrRA05oN52Z2ZHM9qDuHNu1tQoFiINuVeOICDVLpNGVc56ggN4LKCFwtsKJiydSCNNbk0gIFuWGmEZJefka7yQJk16H3bghbByek3IG0C6UQ00l6pYStGfSgGLHf7wPucxm6cJS8Za1AEhuxrhnzWRNXCba5XvBiPOcHa0zPohTXopn6XJKIeYCgqcv1DlbBus4eqH6CxFbiunNPoXR4r7SbGAjoncWmv7/dRhsej0iOdfmO/+wbdhHzEpXj0G9A3nGjha+xKpp1fvz7jneSAru6ljixPkGwar65ixl93XZsOxR7ou7WP3QGXKj7DaE5pwLBWDRmXb6aXgpz6cqP4X93p2091J04r2FxGwvW8= Reduce some variables that describe the problem

guda-art avatar Sep 22 '25 08:09 guda-art

https://play.vuejs.org/#eNp9UctOwzAQ/JXFl4JUGhU4VWnEQz3AARBw9KWkm+DWsS17E4qq/DvrRA05oN52Z2ZHM9qDuHNu1tQoFiINuVeOICDVLpNGVc56ggN4LKCFwtsKJiydSCNNbk0gIFuWGmEZJefka7yQJk16H3bghbByek3IG0C6UQ00l6pYStGfSgGLHf7wPucxm6cJS8Za1AEhuxrhnzWRNXCba5XvBiPOcHa0zPohTXopn6XJKIeYCgqcv1DlbBus4eqH6CxFbiunNPoXR4r7SbGAjoncWmv7/dRhsej0iOdfmO/+wbdhHzEpXj0G9A3nGjha+xKpp1fvz7jneSAru6ljixPkGwar65ixl93XZsOxR7ou7WP3QGXKj7DaE5pwLBWDRmXb6aXgpz6cqP4X93p2091J04r2FxGwvW8= Reduce some variables that describe the problem

Ohh yeah, that's right. Vue sets patching flags, so it sees the content of the div is static so it says "don't patch", but because the keys are cooked it will do it wrong.

benjamin-larsen avatar Sep 22 '25 09:09 benjamin-larsen