Model approach used in checkbox tree is incompatible with Vue 3
While working on &7203 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.toggleAllOptions
we will write something liketoggleAllOptions(tree)
. Since we will be getting rid ofthis
our 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.observable
withVue.reactive
-
implement
models
as 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)