キープアライブとは何ですか?次の記事では、vue 組み込みコンポーネントのキープアライブについての理解を説明します。皆様のお役に立てれば幸いです。
キープアライブは
vue##です# の組み込みコンポーネントは、コンポーネントの切り替え中に状態をメモリに保持して、DOM
のレンダリングが繰り返されるのを防ぐことができます。 [関連する推奨事項: vuejs ビデオ チュートリアル
、Web フロントエンド開発 ]
動的コンポーネントをラップする場合、非アクティブなコンポーネントはキャッシュされたインスタンスを破棄する代わりに。
次の props
プロパティを設定できます:
の基本的な使用法について: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:html;toolbar:false;"><keep-alive>
<component :is="view"></component>
</keep-alive></pre><div class="contentsignin">ログイン後にコピー</div></div>
使用
とexclude
: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:html;toolbar:false;"><keep-alive include="a,b">
<component :is="view"></component>
</keep-alive>
<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
<component :is="view"></component>
</keep-alive>
<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="[&#39;a&#39;, &#39;b&#39;]">
<component :is="view"></component>
</keep-alive></pre><div class="contentsignin">ログイン後にコピー</div></div>
マッチングでは、最初にコンポーネント自体の
オプションがチェックされ、name
オプションが使用できない場合は、そのローカル登録名と一致します。 (親コンポーネント コンポーネント
オプション キー値)、匿名コンポーネントは一致できませんキープアライブ キャッシュが設定されたコンポーネントには、さらに 2 つのライフ サイクル フック (
および deactivated
):
beforeCreate
> created
> マウント
> アクティブ化
> ... ... > beforeRouteLeave
> 非アクティブ化
コンポーネントに再度入る場合: activated
> ... ... > beforeRouteLeave
> deactivated
## 例:
ホームページ
–>リストページ–>
ビジネス詳細ページ##から移動する場合#–>
に戻る。この時点で、リスト ページは homepage
–> から keep-alive
する必要があります。
–>ビジネス詳細ページ
–>リストページに戻る(キャッシュが必要)
–>ホームページに戻る(キャッシュが必要) )
–>もう一度リスト ページにアクセスします (キャッシュする必要はありません)
、この時点で、ページの キープアライブ
を制御できます。ルーティングに
keepAlive
属性を設定して、キャッシュが必要かどうかを決定します。
{ path: 'list', name: 'itemList', // 列表页 component (resolve) { require(['@/pages/item/list'], resolve) }, meta: { keepAlive: true, title: '列表页' } }
Use<keep-alive>
<div id="app" class='wrapper'> <keep-alive> <!-- 需要缓存的视图组件 --> <router-view v-if="$route.meta.keepAlive"></router-view> </keep-alive> <!-- 不需要缓存的视图组件 --> <router-view v-if="!$route.meta.keepAlive"></router-view> </div>
3. 原理分析
に組み込まれたコンポーネントです ソースコードの場所: src/core /components/keep-alive.js
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">export default {
name: &#39;keep-alive&#39;,
abstract: true,
props: {
include: [String, RegExp, Array],
exclude: [String, RegExp, Array],
max: [String, Number]
},
created () {
this.cache = Object.create(null)
this.keys = []
},
destroyed () {
for (const key in this.cache) {
pruneCacheEntry(this.cache, key, this.keys)
}
},
mounted () {
this.$watch(&#39;include&#39;, val => {
pruneCache(this, name => matches(val, name))
})
this.$watch(&#39;exclude&#39;, val => {
pruneCache(this, name => !matches(val, name))
})
},
render() {
/* 获取默认插槽中的第一个组件节点 */
const slot = this.$slots.default
const vnode = getFirstComponentChild(slot)
/* 获取该组件节点的componentOptions */
const componentOptions = vnode && vnode.componentOptions
if (componentOptions) {
/* 获取该组件节点的名称,优先获取组件的name字段,如果name不存在则获取组件的tag */
const name = getComponentName(componentOptions)
const { include, exclude } = this
/* 如果name不在inlcude中或者存在于exlude中则表示不缓存,直接返回vnode */
if (
(include && (!name || !matches(include, name))) ||
// excluded
(exclude && name && matches(exclude, name))
) {
return vnode
}
const { cache, keys } = this
/* 获取组件的key值 */
const key = vnode.key == null
// same constructor may get registered as different local components
// so cid alone is not enough (#3269)
? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : &#39;&#39;)
: vnode.key
/* 拿到key值后去this.cache对象中去寻找是否有该值,如果有则表示该组件有缓存,即命中缓存 */
if (cache[key]) {
vnode.componentInstance = cache[key].componentInstance
// make current key freshest
remove(keys, key)
keys.push(key)
}
/* 如果没有命中缓存,则将其设置进缓存 */
else {
cache[key] = vnode
keys.push(key)
// prune oldest entry
/* 如果配置了max并且缓存的长度超过了this.max,则从缓存中删除第一个 */
if (this.max && keys.length > parseInt(this.max)) {
pruneCacheEntry(cache, keys[0], keys, this._vnode)
}
}
vnode.data.keepAlive = true
}
return vnode || (slot && slot[0])
}
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
コンポーネントには
がなく、代わりに
render が使用され、render が自動的に実行されることがわかります。
コンポーネントがレンダリングされるときの関数。this.cache
は、キャッシュする必要があるコンポーネントを保存するために使用されるオブジェクトです。次の形式で保存されます:
this.cache = { 'key1':'组件1', 'key2':'组件2', // ... }
コンポーネントが破棄されるときに実行されますpruneCacheEntry
function
function pruneCacheEntry ( cache: VNodeCache, key: string, keys: Array<string>, current?: VNode ) { const cached = cache[key] /* 判断当前没有处于被渲染状态的组件,将其销毁*/ if (cached && (!current || cached.tag !== current.tag)) { cached.componentInstance.$destroy() } cache[key] = null remove(keys, key) }
inマウントされた
フック関数、次のように:
mounted () { this.$watch('include', val => { pruneCache(this, name => matches(val, name)) }) this.$watch('exclude', val => { pruneCache(this, name => !matches(val, name)) }) }
If include
または exclude
変更されました。これは、キャッシュする必要があるコンポーネントを定義するためのルールが変更されたことを意味します。キャッシュする必要のないコンポーネントのルールが変更された場合は、pruneCache
関数を実行します。関数は次のとおりです。
function pruneCache (keepAliveInstance, filter) { const { cache, keys, _vnode } = keepAliveInstance for (const key in cache) { const cachedNode = cache[key] if (cachedNode) { const name = getComponentName(cachedNode.componentOptions) if (name && !filter(name)) { pruneCacheEntry(cache, key, keys, _vnode) } } } }
この中の this.cache
オブジェクトが関数内で走査され、各項目の name
値が取得され、新しいキャッシュ ルールと一致するために使用されます。一致しない場合は、その値が新しいキャッシュ ルール。コンポーネントをキャッシュ ルールに基づいてキャッシュする必要がなくなった場合は、pruneCacheEntry
関数を呼び出して、
オブジェクトからコンポーネントを削除します。 keep-alive について
の最も強力なキャッシュ関数は、render
関数 に実装されています。まず、コンポーネントの
key
値を取得します。 ##
const key = vnode.key == null? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '') : vnode.key
key 値の後に、
this.cache オブジェクトに移動して、この値があるかどうかを確認します。ある場合は、コンポーネントにキャッシュ、つまり、次のようにキャッシュにヒットします:
/* 如果命中缓存,则直接从缓存中拿 vnode 的组件实例 */ if (cache[key]) { vnode.componentInstance = cache[key].componentInstance /* 调整该组件key的顺序,将其从原来的地方删掉并重新放在最后一个 */ remove(keys, key) keys.push(key) }
直接从缓存中拿 vnode
的组件实例,此时重新调整该组件key
的顺序,将其从原来的地方删掉并重新放在this.keys
中最后一个
this.cache
对象中没有该key
值的情况,如下:
/* 如果没有命中缓存,则将其设置进缓存 */ else { cache[key] = vnode keys.push(key) /* 如果配置了max并且缓存的长度超过了this.max,则从缓存中删除第一个 */ if (this.max && keys.length > parseInt(this.max)) { pruneCacheEntry(cache, keys[0], keys, this._vnode) } }
表明该组件还没有被缓存过,则以该组件的key
为键,组件vnode
为值,将其存入this.cache
中,并且把key
存入this.keys
中
此时再判断this.keys
中缓存组件的数量是否超过了设置的最大缓存数量值this.max
,如果超过了,则把第一个缓存组件删掉
解决方案可以有以下两种:
每次组件渲染的时候,都会执行beforeRouteEnter
beforeRouteEnter(to, from, next){ next(vm=>{ console.log(vm) // 每次进入路由执行 vm.getData() // 获取数据 }) },
在keep-alive
缓存的组件被激活的时候,都会执行actived
钩子
activated(){ this.getData() // 获取数据 },
注意:服务器端渲染期间avtived
不被调用
以上がVue の組み込みコンポーネントのキープアライブについて理解しましょうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。