keep-alive理解

理解

意味:

これは組み込みコンポーネントです。動的コンポーネントをラップすると、非アクティブなコンポーネント インスタンスを破棄する代わりにキャッシュします。
キープアライブは抽象コンポーネントです。dom 要素としてレンダリングされず、親にも表示されません。コンポーネントチェーン

効果

コンポーネントがキャッシュされた状態にある場合、DOM レンダリングの繰り返しを防ぎ、読み込み時間とパフォーマンスの消費を削減し、ユーザー エクスペリエンスを向上させます。

原理

作成した関数が呼び出されたとき、VNodeの名前がキャッシュ条件を満たしていれば、レンダリング(ページレンダリング)時にキャッシュする必要があるVNode [virtual dom]ノードをthis.cache /に保存します(includeとexcludeで制御可能) )、これは、レンダリングのために以前にキャッシュされた VNode インスタンスを .cache から取り出します。

使用

パラメータ

パラメータ名 価値 説明
含む 文字列または正規表現 名前が一致するコンポーネントのみがキャッシュされます
除外する 文字列または正規表現 名前が一致するコンポーネントはキャッシュされません
最大 番号 最大でキャッシュできるコンポーネント インスタンスの数

注: 包含/除外値は、ルーティング コンポーネント名ではなく、コンポーネント内の名前です。

// router.js
{
    
    
  path: '/home',
  name: 'home',
  component: () => import('../views/home.vue')
},
{
    
     
  path: '/about',
  name: 'about',
  component: () => import('../views/about.vue')
},

//首先声明只有两个页面分别是:home页面和about页面
// App.vue

//所有组件都要缓存【情况一】
<keep-alive>
   <router-view/>
</keep-alive>

//如果只缓存about内容【情况二】
<keep-alive include="about">
   <router-view/>
</keep-alive>

//如果不缓存about内容【情况三】
<keep-alive exclude="about">
   <router-view/>
</keep-alive>

----------------------------------------------------------------------------------------------------------------
补充: include/exclude 值的多种形式。

// 1. 将缓存 name 为 test 的组件(基本)
<keep-alive include='about'>
  <router-view/>
</keep-alive>
	
// 2. 将缓存 name 为 a 或者 b 的组件,结合动态组件使用
<keep-alive include='a,b'>
  <router-view/>
</keep-alive>
	
// 3. 使用正则表达式,需使用 v-bind
<keep-alive :include='/a|b/'>
  <router-view/>
</keep-alive>	
	
// 4.动态判断
<keep-alive :include='includedComponents'>
  <router-view/>
</keep-alive>
	
// 5. 将不缓存 name 为 test 的组件
<keep-alive exclude='home'>
  <router-view/>
</keep-alive>

// 6. 和 `<transition>` 一起使用
<transition>
  <keep-alive>
    <router-view/>
  </keep-alive>
</transition>

// 7. 数组 (使用 `v-bind`)
<keep-alive :include="['a', 'b']">
  <component :is="view"></component>
</keep-alive>

// 关于页about.vue
<template>
  <div class="about">
    <h2>关于页</h2>
    <p @click="pClick">这是一个p标签</p>
  </div>
</template>
<script>
export default{
    
    
  name: 'AboutView',
  components: {
    
    

  },
  methods: {
    
    
    pClick(e) {
    
    
      console.log(e.target.style.color = 'red');
      console.log('p标签被点击了')
    }
  },
  created() {
    
    
    console.log('AboutView created')
  },
  destroyed() {
    
    
    console.log('AboutView destroyed')
  },
}
</script>
//首页home.vue
<template>
  <div class="home">
    <h2>首页</h2>
  </div>
</template>

<script>


export default {
    
    
  name: 'HomeView',
  components: {
    
    

  },
  created() {
    
    
    console.log('HomeView created')
  },
  destroyed() {
    
    
    console.log('HomeView destroyed')
  },
}
</script>

このとき、ケース1であればすべてのコンポーネントがキャッシュされていますが、
ケース2であれば、aboutコンポーネントのpタグ内の内容、つまりホームとスイッチの切り替え時のみがキャッシュされていることがわかります。コンテンツについてのキャッシュが
ケース 3 の場合、それはキャッシュされたホーム コンポーネントです

さらに、
ルートのメタ属性を使用してキャッシュが必要かどうかを制御する別の方法もあります。

about ルートのメタに KeepAlive 属性を true に追加し、現在のルートをキャッシュする必要があることを示します。

// router.js
{
    
    
  path: '/home',
  name: 'home',
  component: () => import('../views/home.vue')
},
{
    
     
  path: '/about',
  name: 'about',
  meta:{
    
    
    keepAlive:true
  },
  component: () => import('../views/about.vue')
},

キープアライブ コードは v-if と組み合わせてラップできます。メタ内の keepAlive が true の場合はキャッシュされ、それ以外の場合はキャッシュされません。

<keep-alive>
  <router-view v-if="$route.meta.keepAlive" />
</keep-alive>
<router-view v-if="!$route.meta.keepAlive" />

その後、実際の開発では、ガードをスターブしてルーティングし、キャッシュ コンポーネントを必要とするキャッシュを実装できます。

export default {
    
    
  beforeRouteLeave(to, from, next) {
    
    
    to.meta.keepAlive = true;
    next();
  }
}
</script>

では、ルートキャッシュを利用する際には必ずライフサイクルフックを使用することになるので、それに関連するライフサイクルフック機能を紹介していきます。

名前 説明
アクティブ化された このフック関数はキープアライブ コンポーネントがアクティブ化されたときに呼び出され、サーバー側のレンダリング中には呼び出されません。
無効化された キープアライブ コンポーネントが非アクティブ化されたときに呼び出されます。サーバー側のレンダリング中にフック関数は呼び出されません。

説明
データはメモリに保持されますが、ページに入るたびに最新のデータを取得したい場合は、アクティブフェーズでデータを取得し、独自に作成したフックでデータを取得する作業を行う必要があります
2 つのライフサイクル フック: アクティブ化と非アクティブ化

active: コンポーネントがアクティブ化されたときに呼び出され、コンポーネントが初めてレンダリングされるときにも呼び出され、その後キープアライブがアクティブ化されるたびに呼び出されます。 deactivated: コンポーネントが非アクティブ化されたときに呼び出されます

注:
これら 2 つのライフ サイクルは、コンポーネントがキープアライブでラップされている場合にのみ呼び出されます。通常のコンポーネントとして使用される場合は、呼び出されません。バージョン 2.1.0 以降では、exclude を使用して除外した後、たとえキープアライブでは、これら 2 つのフックはまだ呼び出されません。また、サーバー側でのレンダリング時にはこのフックは呼び出されません。

データはいつ取得しますか?

キープアライブが導入されると、ページが初めて入力され、フックのトリガー シーケンス:
created==>mounted==》activated、
deactivated は終了時にトリガーされ
、activate は再入力時にトリガーされます。

キープアライブ後、ページ テンプレートが初期化されて初めて HTML フラグメントに解析され、メモリ内のデータは再度入力されたときに再解析されないことがわかっています。
データが変更された場合にのみ、差分更新に VirtualDOM を使用します。したがって、ページエントリのデータ取得もアクティブにする必要があります。
データをダウンロードした後、DOM を手動で操作する部分も実行して有効にする必要があります。

したがって、データ取得コードのコピーをアクティブ化したままにしておくか、作成された部分を除いてコードを作成済みからアクティブ化に直接転送する必要があります。

実際の応用:
keep-alive コンポーネントが使用されていない場合、ページがロールバックするときにページが正直にレンダリングされ、作成されたフックがトリガーされ、ユーザー エクスペリエンスが良くありません。

主な使用シナリオは次のとおりです。 メニューには複数レベルの関係があります [ホームページ-「一覧ページ-」詳細ページ]

ホームページからリスト ページにジャンプすると、リスト ページ コンポーネントが再レンダリングされます。
詳細ページからリスト ページに戻ると、リスト コンポーネントはキャッシュされ、データを再リクエストしません。

// app.vue
<template>
  <div id="app">
    <keep-alive :include="keepAliveInclude">
      <router-view/>
    </keep-alive>
  </div>
</template>

<script>
import {
    
     mapGetters } from 'vuex'
export default {
    
    
  name:'home',
  computed:{
    
    
    ...mapGetters([
      'keepAliveInclude',
    ])
  },
}
</script>

keepAliveInclude の状態更新をストアに保存します

// store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    
    
  state: {
    
    
    // keepAlive缓存组件
    keepAliveInclude:[],
  },
  getters:{
    
    
    keepAliveInclude: state => state.keepAliveInclude,
  },
  mutations: {
    
    
    SET_KEEPALIVEINCLUDE:(state, keepAliveInclude) => {
    
    
      state.keepAliveInclude = keepAliveInclude;
    }
  },
  actions: {
    
    
    setKeepAliveInclude({
     
      commit }, keepAliveInclude){
    
    
      commit("SET_KEEPALIVEINCLUDE", keepAliveInclude)
    },
  },
})

キャッシュする必要があるページのリスト.vue

<template>
  <div>
    <button @click="goHome">首页</button>
    <button @click="goDetail">详情</button>
    列表: <input type="text" v-model="inputVal">
  </div>
</template>

<script>
export default {
    
    
  name:'list',
  data(){
    
    
    return {
    
    
      inputVal:'',
    }
  },
  methods:{
    
    
    goDetail(){
    
    
      this.$router.push('./detail')
    },
    goHome(){
    
    
      this.$router.push('./home')
    }
  },
  beforeRouteLeave (to, from, next) {
    
    
    if(to.name == 'detail'){
    
    
      this.$store.dispatch('setKeepAliveInclude',['list'])
    }else{
    
    
      this.$store.dispatch('setKeepAliveInclude',[])
    }
    // next();
    setTimeout(() => {
    
     next(); }, 10); // next()需用定时器包裹,否则多次切换无法缓存
  }
}
</script>

おすすめ

転載: blog.csdn.net/Clover_zlx/article/details/130930807