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

Custom directive binds differs on components vs elements #9876

Open
bponomarenko opened this issue Apr 15, 2019 · 7 comments
Open

Custom directive binds differs on components vs elements #9876

bponomarenko opened this issue Apr 15, 2019 · 7 comments

Comments

@bponomarenko
Copy link

bponomarenko commented Apr 15, 2019

Version

2.6.10

Reproduction link

https://jsfiddle.net/bponomarenko/uom10qd2/

Steps to reproduce

  1. Open browser console.
  2. Click on Toggle button two times.

What is expected?

Directive will emit the same console messages when applied to DOM elements and to components (on init and after click on button).

I'm not sure what should be expected output. Either

bind: first comp
bind: first elem
unbind: first comp
unbind: first elem
bind: first comp
bind: first elem

or

bind: first comp
bind: first elem
unbind: second comp
unbind: second elem
bind: first comp
bind: first elem

What is actually happening?

Messages from the directive are the same on init, but different after button have been clicked.

Actual console output:

bind: first comp
bind: first elem
unbind: first comp
unbind: second elem
bind: second comp
bind: first elem

It seems that order in which directives are applied to DOM elements and components are different. In my setup I have custom directive which relies on some DOM attribute with configuration data. When this custom directive is bound/unbound in a "regular flow" – everything works as expected (directive binds after element attributes are updated). However when directive is bound/unbound in case of Vue "in-place patch strategey", behavior seems to be different.

@posva
Copy link
Member

posva commented Apr 15, 2019

Seems like the directive is called with the old component (because it's reused) but it still has old attrs

As a workaround, set a key on one of the components

@posva posva changed the title Custom directive binds differently in a "regular flow" and in "in-place patch strategy". Custom directive binds differs on components vs elements Apr 15, 2019
@pistis
Copy link

pistis commented Apr 15, 2019

@bponomarenko
What @posva said is already covered in the documentation.
You can refer to this.

https://vuejs.org/v2/guide/conditional.html#Controlling-Reusable-Elements-with-key

@bponomarenko
Copy link
Author

bponomarenko commented Apr 16, 2019

@posva @pistis Thanks for the answer. Yeah, that is what we used eventually as a workaround, I had to mention that in the ticket. However presence of key attribute will not allow to use Vue.js rendering optimisations. Would be great to have it fixed.

@Justineo
Copy link
Member

The optimization is based on that you have stateless elements so Vue won’t bother to take care of correctly managing event handlers or local states when trying to reuse an element. So I think this is not a bug but can be potentially improved in our docs so that our users can understand this more easily.

@bponomarenko
Copy link
Author

@Justineo I understand the concepts behind an optimization itself. In my situation, custom directive is responsible for adding the state attribute to element on bind and removing that attribute on unbind. And directive is perfectly added/removed when component is re-used by Vue.js. However order of component properties update and directive initialization is different in different moments of component lifetime, which makes it hard to develop custom directives.
Indeed additional documentation on these optimization techniques might be helpful, but inconsistent directives lifecycle events are rather a bug to fix in my opinion.

@SuperStar518
Copy link

As a workaround, set a key on one of the components

@Daniel4Digital
Copy link

I am using a directive of vue-clipboard2 and this bug happened, the bug report comes from 2019: Inndy/vue-clipboard2#75

I've made a PR there that would bypass this issue, but like @bponomarenko said, the order should be fixed. Doesn't make sense for a directive to start to unbind without bind it first.
In the directive above, the key solution doesn't work...

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

6 participants