vue中使用keep- alive緩存機(jī)制,切換標(biāo)簽含有iframe標(biāo)簽的界面會(huì)被重新刷新的問題處理

項(xiàng)目上遇到一個(gè)這樣的需求舅巷,就是在打開含有iframe界面時(shí)羔味,去切換標(biāo)簽,切回含有iframe界面的時(shí)候钠右,要求iframe界面不刷新赋元。vue框架中,我們?nèi)ヌ幚泶祟悊栴}飒房,通常馬上就會(huì)想到去使用vue框架中自帶的keep-alive組件搁凸,所以一開始我也是去使用了keep-alive,但是發(fā)現(xiàn)沒有達(dá)到預(yù)期效果,后面通過研究和查閱資料發(fā)現(xiàn)狠毯,在vue項(xiàng)目中加入了含有iframe的頁面护糖,在路由切換的過程中,使用keep-alive是達(dá)不到數(shù)據(jù)緩存的效果的嚼松。

2嫡良、使用keep-alive緩存不了iframe界面原因

(1)vue中的keep-alive 【1】原理:Vue 的緩存機(jī)制并不是直接存儲(chǔ) DOM 結(jié)構(gòu),而是將 DOM 節(jié)點(diǎn)抽象成了一個(gè)個(gè) VNode節(jié)點(diǎn)献酗。因此寝受,Vue 的 keep-alive 緩存也是基于 VNode節(jié)點(diǎn) 而不是直接存儲(chǔ) DOM 節(jié)點(diǎn)。在需要渲染的時(shí)候從Vnode渲染到真實(shí)DOM上罕偎。 【2】參數(shù):Keep-alive 組件提供了 include 和 exclude 兩個(gè)屬性很澄,允許組件有條件的進(jìn)行緩存。   include: 字符串或正則表達(dá)式。只有匹配的組件會(huì)被緩存甩苛。   exclude: 字符串或正則表達(dá)式蹂楣。任何匹配的組件都不會(huì)被緩存。 【3】Keep-alive 組件提供了兩個(gè)生命鉤子函數(shù)浪藻,分別是 activated 和 deactivated 捐迫。   activated :當(dāng)頁面存在緩存的時(shí)候執(zhí)行該函數(shù)。   deactivated :在頁面結(jié)束時(shí)觸發(fā)該方法爱葵,可清除掉滾動(dòng)方法等緩存施戴。 (2)iframe中keep-alive機(jī)制失效原因:iframe頁里的內(nèi)容并不屬于節(jié)點(diǎn)的信息,所以使用keep-alive依然會(huì)重新渲染iframe內(nèi)的內(nèi)容萌丈。而且iframe每一次渲染就相當(dāng)于打開一個(gè)新的網(wǎng)頁窗口赞哗,即使把節(jié)點(diǎn)保存下來,在渲染時(shí)iframe頁還是刷新的辆雾。

3肪笋、vue中實(shí)現(xiàn)iframe內(nèi)容緩存的思路

(1)保存iframe頁里的節(jié)點(diǎn)信息我們很難去操作,這個(gè)時(shí)候我們就該想是否能在vue的route-view節(jié)點(diǎn)上動(dòng)些手腳度迂。 (2)我們可以在切換不含iframe的界面時(shí)使用vue路由藤乙,在切換含iframe頁的界面時(shí)利用v-show來控制顯示隱藏,使iframe的節(jié)點(diǎn)不被刪除惭墓,以此來防止界面節(jié)點(diǎn)被重新更新坛梁,從而達(dá)到保存iframe節(jié)點(diǎn)數(shù)據(jù)的效果。 具體該怎么操作呢腊凶?請(qǐng)繼續(xù)往下看: 第一步:我們先需要修改一下路由配置划咐,如下:

{
    path: '/printReportShow',
    component: Layout,
    redirect: '/printReportShow',
    hidden: false,
    name: 'Layout',
    children: [
      {
        path: '/printReportShow',
        iframeComponent: printReportShow,
        name: 'printReportShow',
        hidden: false,
        meta: {title: '打印預(yù)覽',}
      }
    ]
  },

從以上代碼,不難看出/printReportShow就是我們要跳轉(zhuǎn)的路由地址钧萍,我們可以看到printReportShow的路由配置中組件我寫的是iframeComponent而非官方教程中的component褐缠,這樣造成的后果就是在 router-view 節(jié)點(diǎn)中渲染時(shí),頁面顯示的是空白頁风瘦。 第二步:修改主界面AppMain.vue(你的可能不叫這個(gè))中的template队魏,添加vue的內(nèi)置組件component,如下:

<template>
  <section class="app-main">
    <transition name="move" mode="out-in" @enter="onEnter">
      <keep-alive :include="cachedViews">
        <router-view :key="key" />
      </keep-alive>
    </transition>
    <!--iframe頁-->
    <component
      v-for="item in hasOpenComponentsArr"
      :key="item.children[0].name"
      :is="item.children[0].name"
      v-show="$route.path === item.path"
    ></component>
  </section>
</template>

從以上代碼我們可以看到万搔,iframe節(jié)點(diǎn)數(shù)據(jù)在根節(jié)點(diǎn)App.vue渲染時(shí)器躏,也隨即跟著渲染了,但是考慮到性能原因蟹略,對(duì)此我們選擇將iframe的顯示做成懶加載形式的登失,只有在用戶進(jìn)入相應(yīng)的頁面時(shí)才觸發(fā)渲染,在渲染完畢后再通過v-show去控制界面在切換時(shí)的顯示與隱藏挖炬。 第三步:AppMain.vue中具體的邏輯處理

<script>
import Vue from 'vue';
export default {
  name: 'AppMain',
  computed: {
    // 實(shí)現(xiàn)懶加載揽浙,只渲染已經(jīng)打開過(hasOpen:true)的iframe頁
    hasOpenComponentsArr() {
      return this.componentsArr.filter(item => {
        return item.children[0].hasOpen
      });
    }
  },
  data() {
    return {
      componentsArr: []
    }
  },
  watch: {
    $route() {
      // 判斷當(dāng)前路由是否iframe頁
      this.isOpenIframePage();
    }
  },
  created() {
    // 設(shè)置iframe頁的數(shù)組對(duì)象
    const componentsArr = this.getComponentsArr();
    componentsArr.forEach((item) => {
      // Vue.component(item.name, item.component);
      Vue.component(item.children[0].name, item.children[0].component);
    });
    this.componentsArr = componentsArr;
    // 判斷當(dāng)前路由是否iframe頁
    this.isOpenIframePage();
  },
  methods:{
    // 根據(jù)當(dāng)前路由設(shè)置hasOpen
    isOpenIframePage() {
      const target = this.componentsArr.find(item => {
        return item.path === this.$route.path
      });
      if (target && !target.children[0].hasOpen) {
        target.children[0].hasOpen = true;
      }
    },
    // 遍歷路由的所有頁面,把含有iframeComponent標(biāo)識(shí)的收集起來
    getComponentsArr() {
      const router = this.$router;
      const routes = router.options.routes;
      const iframeArr = []
      const singleRoutes = routes[6];
      const printReportObj = {
        name: routes[6].children[0].name,
        path: routes[6].children[0].path,
        hasOpen: false, // 是否打開過,默認(rèn)false
        component: routes[6].children[0].iframeComponent // 組件文件的引用
      }
      singleRoutes.children.splice(0,1);
      singleRoutes.children.push(printReportObj);
      iframeArr.push(singleRoutes);
      return iframeArr
    }
  }
}
</script>

備注:由于我們系統(tǒng)中就涉及到一個(gè)iframe界面馅巷,所以在處理上可能有些地方寫死了膛虫,如果是多iframe的可以自行參考著做相應(yīng)的修改。 4钓猬、拓展

由于切換標(biāo)簽稍刀,含iframe的component組件不會(huì)再觸發(fā)路由鉤子函數(shù)和生命周期函數(shù),導(dǎo)致界面數(shù)據(jù)無法做更新操作敞曹,同時(shí)瀏覽器刷新時(shí)账月,界面數(shù)據(jù)會(huì)有丟失的問題,所以我們可以考慮去監(jiān)聽sessionStorage的值澳迫,以此來更新數(shù)據(jù)局齿。詳情可以看下面這篇文章:vue中如何實(shí)現(xiàn)對(duì)sessionStorage的監(jiān)聽。

4.vue中如何實(shí)現(xiàn)對(duì)sessionStorage的監(jiān)聽

1橄登、使用場景

(1)在vue項(xiàng)目中抓歼,為了在瀏覽器刷新時(shí),頁面數(shù)據(jù)不丟失拢锹,我們會(huì)選擇將數(shù)據(jù)瀏覽器緩存sessionStorage中谣妻。 (2)為了傳遞參數(shù) 由于切換標(biāo)簽,含iframe的組件不會(huì)在觸發(fā)路由鉤子函數(shù)和生命周期函數(shù)卒稳,導(dǎo)致界面數(shù)據(jù)無法做更新操作拌禾,同時(shí)還要解決瀏覽器刷新時(shí),界面數(shù)據(jù)不丟失的問題展哭,所以才考慮到去監(jiān)聽sessionStorage的值,以此來更新數(shù)據(jù)闻蛀。

2匪傍、具體實(shí)現(xiàn)思路

(1)在vue項(xiàng)目main.js文件中,在vue原型上定義resetSetItem,代碼如下:

Vue.prototype.resetSetItem = function (key, newVal) {
  // 創(chuàng)建一個(gè)StorageEvent事件
  var newStorageEvent = document.createEvent('StorageEvent');
  const storage = {
    setItem: function (k, val) {
      sessionStorage.setItem(k, val);
      // 初始化創(chuàng)建的事件
      newStorageEvent.initStorageEvent(key, false, false, k, null, val, null, null);
      // 派發(fā)對(duì)象
      window.dispatchEvent(newStorageEvent)
    }
  }
  return storage.setItem(key, newVal);
}

2)通過resetSetItem方法存值觉痛,代碼如下:

 self.resetSetItem('printReportShowQuery', JSON.stringify(query));

3)getItem取值和window.addEventListener監(jiān)聽役衡,代碼如下:

created() {
  let routQuery = {};
  let self = this;
  // ***為resetSetItem函數(shù)對(duì)應(yīng)的第一個(gè)key參數(shù)
  window.addEventListener('***', ()=> {
    let printReportShowQuery = JSON.parse(sessionStorage.getItem('printReportShowQuery'));
    routQuery.url = printReportShowQuery.url;
    routQuery.params = JSON.parse(printReportShowQuery.params);
    self.init(routQuery);
  });
  },
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市薪棒,隨后出現(xiàn)的幾起案子手蝎,更是在濱河造成了極大的恐慌,老刑警劉巖俐芯,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件棵介,死亡現(xiàn)場離奇詭異,居然都是意外死亡吧史,警方通過查閱死者的電腦和手機(jī)邮辽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人吨述,你說我怎么就攤上這事岩睁。” “怎么了揣云?”我有些...
    開封第一講書人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵捕儒,是天一觀的道長。 經(jīng)常有香客問我邓夕,道長刘莹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任翎迁,我火速辦了婚禮栋猖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘汪榔。我一直安慰自己蒲拉,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開白布痴腌。 她就那樣靜靜地躺著雌团,像睡著了一般。 火紅的嫁衣襯著肌膚如雪士聪。 梳的紋絲不亂的頭發(fā)上锦援,一...
    開封第一講書人閱讀 51,488評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音剥悟,去河邊找鬼灵寺。 笑死,一個(gè)胖子當(dāng)著我的面吹牛区岗,可吹牛的內(nèi)容都是我干的略板。 我是一名探鬼主播,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼慈缔,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼叮称!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起藐鹤,我...
    開封第一講書人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤瓤檐,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后娱节,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體挠蛉,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年肄满,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了碌秸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绍移。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖讥电,靈堂內(nèi)的尸體忽然破棺而出蹂窖,到底是詐尸還是另有隱情,我是刑警寧澤恩敌,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布瞬测,位于F島的核電站,受9級(jí)特大地震影響纠炮,放射性物質(zhì)發(fā)生泄漏月趟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一恢口、第九天 我趴在偏房一處隱蔽的房頂上張望孝宗。 院中可真熱鬧,春花似錦耕肩、人聲如沸因妇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽婚被。三九已至,卻和暖如春梳虽,著一層夾襖步出監(jiān)牢的瞬間址芯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來泰國打工窜觉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留谷炸,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓禀挫,卻偏偏與公主長得像旬陡,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子特咆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容