vue3 自定义tabbar 缓存当前页面的数据

本文介绍了如何使用Vue封装自定义TabBar组件,监听路由变化以管理tabsList和keepaliveName数据,实现组件的动态缓存,确保切换Tab时保持内容一致性。
摘要由CSDN通过智能技术生成

整体思路

1. 封装自定义tabbar组件 需要监听当前的路由路径,当路由发生变化的时候,需要存tabslist和 keepaliveName的数据

2. 封装存储和移除tabsList的数据的方法(pinia)用于显示页签

3. 封装缓存和移除的组件名字keepaliveName的方法(pinia)用于keepalive组件的include属性

4. 在路由出口的位置需要使用keepalive组件和component组件 缓存组件的数据 实现切换tab后,上一tab页的内容仍然保留

第一步  封装自定义tabbar组件

<div class="tabs-box">
    <div class="tabs-menu">
      <el-tabs
        v-model="tabsMenuValue"
        type="card"
        @tab-click="tabClick"
        @tab-remove="tabRemove"
      >
        <el-tab-pane
          v-for="item in tabsMenuList"
          :key="item.path"
          :label="item.title"
          :name="item.path"
          :closable="item.close"
        >
          <template #label>
            <el-icon class="tabs-icon" v-show="item.icon && tabsIcon"></el-icon>
            {{ item.title }}
          </template>
        </el-tab-pane>
      </el-tabs>
    </div>
  </div>


// Tab Click 点击每一个tab跳转到对应的页面
const tabClick = (tabItem: TabsPaneContext) => {
  const fullPath = tabItem.props.name as string
  console.log('fullPath', fullPath)
  router.push(fullPath)
}

// Remove Tab 点击每一个tab上的icon移除当前tab
const tabRemove = (fullPath: TabPaneName) => {
  //tab-remove方法 会返回一个回调函数 fullpath
  console.log('fullPath', fullPath)
  const name =
    tabStore.tabsMenuList.filter((item: any) => item.path == fullPath)[0]
      .name || ''
// 移除keepaliveName和tabsList的数据
  keepAliveStore.removeKeepAliveName(name)
  tabStore.removeTabs(fullPath as string, fullPath == route.fullPath)
}

// 监听路由的变化(防止浏览器后退/前进不变化 tabsMenuValue)
watch(
  () => route.fullPath,
  () => {
    const routeList = route.fullPath.split('/')
    const name = routeList[routeList.length - 1]
    tabsMenuValue.value = route.fullPath
    const tabsParams = {
      icon: route.meta.icon as string,
      title: route.meta.title as string,
      path: route.fullPath,
      name: name as string,
      close: true,
    }
// 当路由发生变化时 给tabsList 和 keepaliveName中添加数据
    tabStore.addTabs(tabsParams)
    keepAliveStore.addKeepAliveName(name)
  },
// 一来进来页面就监听
  { immediate: true },
)

第二步  封装存储和移除tabsList的数据的方法

// addtab
  async addTabs(tabItem: TabsMenuProps) {
      //要往tabsList添加的tab 是否在list中,如果不在就添加
      console.log('tabItem', tabItem)
      const res1 = this.tabsMenuList.every((item) => {
        console.log('item', item)
        return item.path !== tabItem.path
      })
      console.log('res1', res1)
      if (this.tabsMenuList.every((item) => item.path !== tabItem.path)) {
        this.tabsMenuList.push(tabItem)
        console.log('tabsMenuList', this.tabsMenuList)
      }
    },
    // Remove Tabs
    async removeTabs(tabPath: string, isCurrent: boolean = true) {
      // isCurrent 判断当前的fullpath和路由获取到的fullpath 是否一致
      // 1. 把当前tabs关闭
      // 2. 显示上一个tabs内容
      const tabsMenuList = this.tabsMenuList
      if (isCurrent) {
        tabsMenuList.forEach((item, index) => {
          if (item.path !== tabPath) return
          // ?什么情况下会 加1 显示上一个tabs内容
          const nextTab = tabsMenuList[index + 1] || tabsMenuList[index - 1]
          if (!nextTab) return
          router.push(nextTab.path)
        })
      }
      //把当前tabs关闭
      this.tabsMenuList = tabsMenuList.filter((item) => item.path !== tabPath)
    },

第三步 封装缓存和移除的组件名字keepaliveName的方法

// Add KeepAliveName
    async addKeepAliveName(name: string) {
      !this.keepAliveName.includes(name) && this.keepAliveName.push(name)
      // console.log('keepAliveName3333333', this.keepAliveName)
    },
    // Remove KeepAliveName
    async removeKeepAliveName(name: string) {
      this.keepAliveName = this.keepAliveName.filter((item) => item !== name)
    },

第四步  在路由出口的位置缓存数据

<router-view v-slot="{ Component }">
    <!-- transition 过渡动画 -->
    <transition name="fade">
      <!-- 渲染layout一级路由组件的子路由 -->
      <!--:key 每次切换时,通过修改 key 的值,可以避免缓存中的组件被复用,从而达到刷新组件的目的-->
      <keep-alive :include="keepAliveName">
        <component :is="Component" v-if="flag" :key="route.path" />
      </keep-alive>
    </transition>
  </router-view>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值