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

Vue unmount не очищает компоненты с v-once, созданные через vdom #1217

Open
shining-mind opened this issue Apr 5, 2024 · 3 comments

Comments

@shining-mind
Copy link
Contributor

shining-mind commented Apr 5, 2024

Пример в ветке examples/1217

Как воспроизвести баг

  1. Собрать демо страницу с примером
  2. Нажать на кнопку Destroy b-dummy (это уничтожит b-virtual-scroll)
  3. Нажать на кнопку Reload all components

ФР: получена ошибка TypeError: Cannot use 'in' operator to search for 'getRoot' in undefined

Пояснение к багу

  1. Есть b-virtual-scroll, внутри него рендерится компонент (b-dummy) внутри которого есть другой компонент (b-remote-provider) с v-once
  2. При уничтожении b-virtual-scroll, уничтожается только b-dummy, а b-remote-provider продолжает жить (утечка памяти)

P.s. если удалить v-once, то vue.unmount() удалит и b-remote-provider.

Если бы не было вызова vue.unmount, то продолжали бы жить вообще все внутренние компоненты b-dummy, так как b-virtuall-scroll вызывает destroy только непосредственно у item'а.

Дифф: https://github.com/V4Fire/Client/compare/v4...examples/1217?expand=1

@shining-mind
Copy link
Contributor Author

shining-mind commented Apr 8, 2024

Проблема оказалась куда серьезнее - это баг на уровне Vue, вот пример в песочнице. Надо открыть консоль и покликать на кнопку "Change state", будет видно, что с каждым переключением количество событий растет, потому что не отрабатывает unmount.

Также есть баг в репозитории Vue. Можно заменить v-once на v-memo=[] - функционально это тоже самое, однако Vue при этом вызывает unmount для таких узлов.

@boikovdv
Copy link
Contributor

boikovdv commented Apr 8, 2024

Дополнительно поизучал внутри vue и что под капотом у v-once.
Как только встречается эта директива, то в целях оптимизации он перестает добавлять всех детей в dynamicChildren, поскольку считает что там дальше статичный контент который не должен меняться. Это сделано чтоб даже не ходить внутрь и не пытаться апдейтить что-либо при изменениях.
Есть у этого наблюдаемый сайдэффект что дальше даже при удалении не вызываются анмаунты, поскольку он даже не знает для кого их вызвать.
Это справедливо не только для самого компонента на котором v-once, но и для всего дерева дочерних узлов в шаблоне.
Наши компоненты вовсе нельзя использовать с v-once, поскольку для них никогда не будет вызван деструктор и соответсвенно будет течь async

@kobezzza
Copy link
Contributor

Мб запретим использование v-once?

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

3 participants