Я думал, что целью было кэширование данных, связанных с компонентом, который в данный момент не отображается в DOM
Нет, он не кэширует данные компонента. Он кэширует весь экземпляр компонента (включая все его состояние). Просто он заставляет экземпляр компонента жить, а не уничтожаться ...
Согласно эта ошибка специально разработана для удаления кэша, который он удерживал при удалении элемента со страницы. Так что же мне не хватает?
Точка, которую можно извлечь из этой "ошибки": "всякий раз, когда <keep-alive>
компонент уничтожается (поскольку он сам внутри v-if
), он отбрасывает все кэшированные компоненты .. . "
Зачем мне использовать <keep-alive>
с v-show
? Не является ли смысл v-show
в том, что элемент все еще существует на странице, просто для него CSS установлено, чтобы скрыть его?
Да, это именно точка v-show
и бессмысленно использовать его с <keep-alive>
(поскольку v-show
не приводит к уничтожению / созданию компонента)
По умолчанию элемент теряет данные, когда он скрыт с помощью v-show
?
Нет, компонент, скрытый v-show
, все еще существует в памяти, в дереве компонентов и DOM и сохраняет его состояние ....
Чтобы было ясно, следующий пример, по-видимому, не работает (в соответствии с закрытой ошибкой, которую я в любом случае связал)
<div v-if="lazyLoaded && userClickedToShow">
<keep-alive>
<some-child-component :prop="someLazyLoadedData"></some-child-component>
</keep-alive>
</div>
... да, это не работает, потому что:
v-if === false
уничтожит компонент <keep-alive>
, если он был ранее визуализирован (но это не совсем правильно, потому что <keep-alive>
"без рендеринга" в том смысле, что он просто обеспечивает функциональность и не дает сделать что-либо для DOM, кроме его дочернего компонента). - И
v-if === true
создадут <keep-alive>
и отобразят его дочерние компоненты
Чтобы заставить его работать, вам нужно переместить <keep-alive>
за пределы v-if
:
<keep-alive>
<some-child-component v-if="lazyLoaded && userClickedToShow" :prop="someLazyLoadedData" />
</keep-alive>
Приведенный выше код должен приводить к визуализации some-child-component
(и одновременно помещать его в кэш <keep-alive>
), когда результат условия v-if
равен true
. Когда v-if
переключен на false
, шаблон компонента удаляется из DOM, но компонент остается в кэше, а не уничтожается.
Основное различие между v-if
(вместе с <keep-alive>
) и v-show
в этом случае состоит в том, что при комбо v-if
/ keep-alive
экземпляр компонента сохраняется в памяти, но результат его шаблон не является частью DOM, тогда как для v-show
компонент является живым и соответствующий HTML, который он отображает, является частью DOM (просто скрыт) * 1078 *
И ответить на ваш вопрос .... <keep-alive>
в первую очередь предназначен для динамического c компонента (<component :is="" >
) и Vue -раута в частности ...
UPDATE (... из-за обновленного кода, о котором идет речь )
<div v-if="lazyLoaded && userClickedToShow">
<h2>{{someLazyLoadedData.title}}</h2>
<div id="otherStuff">
...
</div>
<keep-alive>
<some-child-component :prop="someLazyLoadedData"></some-child-component>
</keep-alive>
</div>
Этот код не будет работать должным образом по той же причине, что и в первом примере - если уничтожено keep-alive
(в результате условия v-if
, оцененного как false
), он будет удалить все кэшированные компоненты. keep-alive
- это просто локальный кеш, который будет работать только в том случае, если он сам «рендерится».
Есть ли способ переписать его так, чтобы он соответствовал предполагаемому функционированию?
Ваш лучший вариант - просто обернуть все, что вы хотите, "переключить" в один компонент и использовать этот компонент следующим образом:
<keep-alive>
<my-component v-if="lazyLoaded && userClickedToShow" :prop="someLazyLoadedData" />
</keep-alive>
... все другие варианты потерпят неудачу, как вы можете попытаться увидеть в это демо
Документы
Примечание, <keep-alive>
предназначено для случая, когда у него один прямой ребенок компонент , который переключается. Если имеется несколько условных дочерних элементов, <keep-alive>
требует, чтобы за один раз отображался только один дочерний элемент.
- это не будет работать, если у него более одного отображаемых child
- не будет работать, если дочерний элемент не является компонентом (например,
<div
)