最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue中使用keep-alive動態(tài)刪除已緩存組件方式

 更新時間:2022年08月11日 10:06:23   作者:FighterLiu  
這篇文章主要介紹了vue中使用keep-alive動態(tài)刪除已緩存組件方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

項目場景

在做后臺管理系統(tǒng)的時候,有這樣一個需求:

后臺的界面如下:

點(diǎn)擊左邊的菜單,會在右邊的頂部生成一個個tag導(dǎo)航標(biāo)簽。當(dāng)打開多個tag頁時,用戶可以在多個tag之間進(jìn)行切換。需要在新增,修改頁面切換tag時候,保留之前的信息,不進(jìn)行頁面的刷新。

問題描述

經(jīng)過查詢vue文檔,可以使用keep-alive實現(xiàn)標(biāo)簽路由緩存,實現(xiàn)方式如下:

在路由配置的meta中添加keepAlive,如下:

{
    path: '/actdebt',
    component: Layout,
    redirect: '/actdebt/add',
    children: [
      {
        path: 'add',
        name: 'XXX新增配置',
        meta: {
          keepAlive: true,
        },
        component: () =>
            import (/* webpackChunkName: "page" */'@/views/bankact/actdebt/add')
      }]
  },

然后在頁面中使用v-if做判斷,并且加上key

<keep-alive>
   <router-view :key="$route.fullPath" class="avue-view"             
    v-if="$route.meta.keepAlive" />
</keep-alive>
   <router-view class="avue-view" v-if="!$route.meta.keepAlive" />

使用上面這種方式解決了修改不同記錄的緩存問題,因為不同記錄的fullPath 不一樣,這樣的話key就會不一樣。

但是對于新增和修改同一條記錄還是有緩存問題。例如新增一條記錄保存成功后,下次在打開新增頁面,還是緩存有之前的記錄。

修改頁面也是的,修改同一條記錄保存成功后,再次打開可能還是會有之前的修改數(shù)據(jù)。

解決方案

要解決上面這種問題我想到的解決方案為:在不同的tag導(dǎo)航欄切換的時候,保留緩存數(shù)據(jù)。當(dāng)關(guān)閉tag導(dǎo)航欄或者關(guān)閉頁面的時候,清除緩存。

清除緩存可以在組件里面的deactivated鉤子函數(shù)調(diào)用this.$destroy();但是發(fā)現(xiàn)下次打開這個頁面的時候,新的組件不會被緩存了。

可以利用keep-alive的include,新打開標(biāo)簽時,把當(dāng)前組件名加入到include數(shù)組里,關(guān)閉標(biāo)簽時從數(shù)組中刪除關(guān)閉標(biāo)簽的組件名就可以了。

Include里面的值必須和組件的name屬性保持一致,如下:

但是如果我同一個組件加載了兩次,一個需要緩存,一個不需要緩存。但是他們的name卻是一樣的,還是無法解決問題。

所以是否可以重寫keep-alive源碼,使include可以按照路由地址匹配,而不是按照組件的name匹配。完整的代碼如下:

新建keepAlive.js文件

/**
 * base-keep-alive 主要解決問題場景:多級路由緩存
 * 前提:保證動態(tài)路由生成的route name 值都聲明了且唯一
 * 基于以上對keep-alive進(jìn)行以下改造:
 *   1. 組件名稱獲取更改為路由名稱
 *   2. cache緩存key也更改為路由名稱
 *   3. pruneCache
 */
 const _toString = Object.prototype.toString
 function isRegExp(v) {
   return _toString.call(v) === '[object RegExp]'
 }
 export function remove(arr, item) {
   if (arr.length) {
     const index = arr.indexOf(item)
     if (index > -1) {
       return arr.splice(index, 1)
     }
   }
 }
 /**
  * 1. 主要更改了 name 值獲取的規(guī)則
  * @param {*} opts
  */
 function getComponentName(opts) {
   // return opts && (opts.Ctor.options.name || opts.tag)
   return this.$route.path
 }
 function isDef(v) {
   return v !== undefined && v !== null
 }
 function isAsyncPlaceholder(node) {
   return node.isComment && node.asyncFactory
 }
 function getFirstComponentChild(children) {
   if (Array.isArray(children)) {
     for (let i = 0; i < children.length; i++) {
       const c = children[i]
       if (isDef(c) && (isDef(c.componentOptions) || isAsyncPlaceholder(c))) {
         return c
       }
     }
   }
 }
 function matches(pattern, name) {
   if (Array.isArray(pattern)) {
     return pattern.indexOf(name) > -1
   } else if (typeof pattern === 'string') {
     return pattern.split(',').indexOf(name) > -1
   } else if (isRegExp(pattern)) {
     return pattern.test(name)
   }
   /* istanbul ignore next */
   return false
 }
 
 function pruneCache(keepAliveInstance, filter) {
   const { cache, keys, _vnode } = keepAliveInstance
   for (const key in cache) {
     const cachedNode = cache[key]
     if (cachedNode) {
       // ------------ 3. 之前默認(rèn)從router-view取儲存key值, 現(xiàn)在改為路由name, 所以這里得改成當(dāng)前key
       // const name = getComponentName.call(keepAliveInstance, cachedNode.componentOptions)
       const name = key
       if (name && !filter(name)) {
         pruneCacheEntry(cache, key, keys, _vnode)
       }
     }
   }
 }
 
 function pruneCacheEntry(
   cache,
   key,
   keys,
   current
 ) {
   const cached = cache[key]
   if (cached && (!current || cached.tag !== current.tag)) {
     cached.componentInstance.$destroy()
   }
   cache[key] = null
   remove(keys, key)
 }
 
 const patternTypes = [String, RegExp, Array]
 
 export default {
   name: 'keep-alive',
   // abstract: true,
   props: {
     include: patternTypes,
     exclude: patternTypes,
     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('include', val => {
       pruneCache(this, name => matches(val, name))
     })
     this.$watch('exclude', val => {
       pruneCache(this, name => !matches(val, name))
     })
   },
 
   render() {
     const slot = this.$slots.default
     const vnode = getFirstComponentChild(slot)
     const componentOptions = vnode && vnode.componentOptions
     if (componentOptions) {
       // check pattern
       const name = getComponentName.call(this, componentOptions)
       // ---------- 對于沒有name值得設(shè)置為路由得name, 支持vue-devtool組件名稱顯示
       if (!componentOptions.Ctor.options.name) {
         vnode.componentOptions.Ctor.options.name
       }
       const { include, exclude } = this
       if (
         // not included
         (include && (!name || !matches(include, name))) ||
         // excluded
         (exclude && name && matches(exclude, name))
       ) {
         return vnode
       }
 
       const { cache, keys } = this
       // ------------------- 儲存的key值, 默認(rèn)從router-view設(shè)置的key中獲取
       // const key = vnode.key == null
       //   ? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
       //   : vnode.key
 
       // ------------------- 2. 儲存的key值設(shè)置為路由中得name值
       const key = name
 
       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
         if (this.max && keys.length > parseInt(this.max)) {
           pruneCacheEntry(cache, keys[0], keys, this._vnode)
         }
       }
       vnode.data.keepAlive = true
     }
     return vnode || (slot && slot[0])
   }
 }

然后在main.js中引入該組件,使組件可以全局使用

在頁面直接使用BaseKeepAlive:

 <BaseKeepAlive :include="cachetags">
            <router-view :key="$route.fullPath" class="avue-view" />
          </BaseKeepAlive>

cachetags 方法就是新打開標(biāo)簽時,把當(dāng)前組件名加入到include數(shù)組里,關(guān)閉標(biāo)簽時從數(shù)組中刪除關(guān)閉標(biāo)簽,源碼如下:

computed: {
    ...mapGetters(['isLock',  "tagList",'isCollapse', 'website']),
    cachetags(){
      let list=[]
      for(let item of this.tagList){
        if(!validatenull(item.keepalive)&&item.keepalive){
        list.push(item.value)
        }
      
      }
    return list.join(',')
    }
    },

方法中的tagList就是導(dǎo)航欄當(dāng)前打開相應(yīng)的tag集合如下圖所示

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • webpack搭建vue環(huán)境時報錯異常解決

    webpack搭建vue環(huán)境時報錯異常解決

    這篇文章主要介紹了webpack搭建vue環(huán)境時報錯異常解決,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • 在vue項目中,使用axios跨域處理

    在vue項目中,使用axios跨域處理

    下面小編就為大家分享一篇在vue項目中,使用axios跨域處理,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-03-03
  • Vue項目移動端滾動穿透問題的實現(xiàn)

    Vue項目移動端滾動穿透問題的實現(xiàn)

    這篇文章主要介紹了Vue項目移動端滾動穿透問題的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • Vue-CLI 3 scp2自動部署項目至服務(wù)器的方法

    Vue-CLI 3 scp2自動部署項目至服務(wù)器的方法

    這篇文章主要介紹了Vue-CLI 3 scp2自動部署項目至服務(wù)器的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • vue創(chuàng)建項目卡住不動,vue?create?project卡住不動的解決

    vue創(chuàng)建項目卡住不動,vue?create?project卡住不動的解決

    這篇文章主要介紹了vue創(chuàng)建項目卡住不動,vue?create?project卡住不動的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • vue 使用iView組件中的Table實現(xiàn)定時自動滾動效果

    vue 使用iView組件中的Table實現(xiàn)定時自動滾動效果

    要在css中設(shè)置table的高度,使數(shù)據(jù)過多時出現(xiàn)滾動條,將縱向設(shè)置為overflow-y: auto;橫向設(shè)置隱藏 overflow-x: hidden,接下來通過本文介紹vue使用iView組件中的Table實現(xiàn)定時自動滾動效果,需要的朋友可以參考下
    2024-05-05
  • vue+axios實現(xiàn)文件上傳的實時進(jìn)度條

    vue+axios實現(xiàn)文件上傳的實時進(jìn)度條

    最近用vue寫上傳的時候,遇到一個需求就是頁面上展示上傳的進(jìn)度條,之后寫過一次,但是用的是假交互,直接從0-100,今天分享一下用axios自帶的onUploadProgress來完成這個小需求,感興趣的朋友可以參考下
    2024-01-01
  • vue動態(tài)添加store、路由和國際化配置方式

    vue動態(tài)添加store、路由和國際化配置方式

    這篇文章主要介紹了vue動態(tài)添加store、路由和國際化配置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • vue如何通過props方式在子組件中獲取相應(yīng)的對象

    vue如何通過props方式在子組件中獲取相應(yīng)的對象

    這篇文章主要介紹了vue如何通過props方式在子組件中獲取相應(yīng)的對象,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • Vue + Scss 動態(tài)切換主題顏色實現(xiàn)換膚的示例代碼

    Vue + Scss 動態(tài)切換主題顏色實現(xiàn)換膚的示例代碼

    這篇文章主要介紹了Vue + Scss 動態(tài)切換主題顏色實現(xiàn)換膚的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04

最新評論

准格尔旗| 凤台县| 老河口市| 松滋市| 静乐县| 弋阳县| 茌平县| 金平| 沧州市| 西城区| 贡嘎县| 田东县| 赣州市| 额尔古纳市| 新建县| 饶河县| 黄陵县| 兴仁县| 桐城市| 黔西| 博野县| 于田县| 瓮安县| 来安县| 汽车| 上蔡县| 许昌县| 海门市| 东莞市| 瑞昌市| 南江县| 河北区| 新宁县| 波密县| 娄烦县| 淮北市| 扎囊县| 敦化市| 新竹县| 大连市| 萝北县|