Какой смысл Vuejs ? - PullRequest
       117

Какой смысл Vuejs ?

1 голос
/ 21 января 2020

В основном, что это говорит. Какой смысл <keep-alive>? Это может показаться глупым, но я подумал, что целью было кэширование данных, связанных с компонентом, который в данный момент не отображается в DOM. Согласно эта ошибка / проблема , <keep-alive> равна , в частности , предназначенной для удаления кэша, который он удерживал, когда элемент был удален со страницы. Так чего мне не хватает?

Зачем мне использовать <keep-alive> с v-show? Разве не смысл v-show в том, что элемент все еще существует на странице, просто для него установлен CSS, чтобы скрыть его? По умолчанию элемент теряет данные, когда он скрыт с помощью v-show?

Чтобы быть понятным, следующий пример, по-видимому, не будет работать (в соответствии с закрытой ошибкой / проблемой, с которой я связан в любом случае):

<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> в этом сценарии кэширует данные, связанные с <some-child-component>, после того, как он был загружен, и если пользователь щелкнет, чтобы показать (возможно, это много данных, которые я не хочу в DOM по соображениям производительности, если пользователь специально не щелкает, чтобы показать его или что-то еще), он переключает отображение, но сохраняет условия поиска или что-то, что произошло в компоненте.

Есть ли способ переписать это, которое бы соответствовало тому, как <keep-alive> должен функционировать? Должен ли я связываться с is на <component> и просто установить его на ноль, если я не хочу, чтобы он отображался в данный момент? Что-то вроде этого?

<keep-alive>
    <component :is="lazyLoaded && userClickedToShow ? 'SomeChildComponent' : ''" :prop="lazyLoaded && someLazyLoadedData"></component>
<keep-alive>

Кажется, что запутывает то, что на самом деле там происходит, даже если это работает. Также предположим, что реквизит SomeChildComponent может занять false, чего он не может сделать. Я не фанат этого варианта. Возможно, немного лучше было бы заключить все это в блок if, может быть?

<div v-if="lazyLoaded">
    <keep-alive>
        <component :is="userClickedToShow ? : 'SomeChildComponent' : ''" :prop="someLazyLoadedData"></component>
    <keep-alive>
</div>

Конечно, это предполагает, что <keep-alive> функционирует в блоке v-if, что может и не произойти , Кроме того, это все еще менее понятно, чем первый способ (это не работает). Я не фанат установки is на '', если только это не единственный способ. И, конечно же, ни один из этих вариантов не позволяет управлять более крупными блоками с помощью условного элемента, при этом поддерживается только элемент.

Просто потратил большую часть двух дней, пытаясь выяснить, почему <keep-alive> был не в состоянии поддерживать жизнь! Надеюсь, что-то простое я просто упускаю!

Редактировать: обновленный исходный пример, чтобы лучше отразить мой сценарий использования.

1 Ответ

4 голосов
/ 21 января 2020

Я думал, что целью было кэширование данных, связанных с компонентом, который в данный момент не отображается в 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>

... да, это не работает, потому что:

  1. v-if === false уничтожит компонент <keep-alive>, если он был ранее визуализирован (но это не совсем правильно, потому что <keep-alive> "без рендеринга" в том смысле, что он просто обеспечивает функциональность и не дает сделать что-либо для DOM, кроме его дочернего компонента).
  2. И 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)
...