Model approach used in checkbox tree is incompatible with Vue 3
While working on &7203 (closed) I've discovered that our models approach taken in checkbox tree is not compatible with Vue 3
What we basically do? We create a tree model inside Vue component. At this point Vue 2 patches this instance (and all underlying node instances) to be reactive, by defining getters/setters on instance
This means that when we invoke any method on models( for example toggleAllOptions Vue 2 is capable to track changes and update our model accordingly
This is not the case for Vue 3. Vue 3 wraps our model in proxy, instead of patching it.
So, any changes which are made inside the model are not tracked by Vue 3 reactivity system (because inside class instances this is pointing to instance, not to the proxy where Vue track changes). Basically this results in this test failiing
What approaches we potentially could take: (this list is not completed, I'm open to new suggestions!):
-
split functions and state (remove classes). So basically instead of calling
tree.toggleAllOptionswe will write something liketoggleAllOptions(tree). Since we will be getting rid ofthisour functions will receive proper Vue proxies for Vue 3 and this approach is compatible with Vue 2 -
Put all state in a dedicated field inside classes, which will be explicitly made reactive using
Vue.observable(something likethis.state = Vue.observable({ /* ... */ })). Since our data will remain explicitly reactive this will be compatible with both Vue2 and Vue3 (in Vue3 we will simply replaceVue.observablewithVue.reactive -
implement
modelsas renderless Vue instance (so created vianew Vue). I'm not a big fan of this approach, but I've seen it on some projects
Important note: we have a number of similar class-based storages in main gitlab-org/gitlab codebase. It would be great to figure out approach, which we will consider universal for such migration (and add it to our frontend documentation)