vue3中处理非tab页不显示底部tabbar

目录

引言

一、解决办法

1、App.vue

 2、myHeader.vue

3、mine.vue

4、info.vue

5、路由处理

二、运行效果

引言

       h5页面底部显示tabbar,大部分页面是不需要展示tabber的,为了提高开发效率,可用如下办法进行:

一、解决办法

       通过监听路由,判断是否该页面为tabbar页面,如果不为tabbar页面,隐藏tab组件;否则,展示tabbar组件

1、App.vue

state.isShowTab 用来判断是否展示tab组件

<template>
  <div class="container">
    <!-- 自定义组件 顶部的title -->
    <my-header />

    <!-- 路由出口 -->
    <router-view />

    <div class="tab-wrap">
      <!-- 底部tabbar -->
      <van-tabbar v-model="active" route v-if="state.isShowTab">
        <van-tabbar-item icon="home-o" to="/home">首页</van-tabbar-item>
        <van-tabbar-item icon="video-o" to="/video">视频</van-tabbar-item>
        <van-tabbar-item icon="contact" to="/mine">我的</van-tabbar-item>
      </van-tabbar>
    </div>
  </div>
</template>

<script>
import { ref, watch, reactive } from "vue";
import { useRoute } from "vue-router";
import myHeader from "../components/myHeader.vue";

export default {
  components: { myHeader },
  setup() {
    const active = ref(0);
    const route = useRoute();

    const state = reactive({
      isShowTab: true, //默认展示底部的tab
    });

    // 监听路由中的信息是否为tab页,如果为tab页,展示,否则,不展示底部tab
    watch(
      () => route.meta,
      (val) => {
        state.isShowTab = val.isTab;
      }
    );
    return { active, state };
  },
};
</script>

 2、myHeader.vue

统一封装顶部的head

<template>
  <van-nav-bar
    :title="barTitle"
    :left-arrow="!isShowBackArrow"
    @click-left="onClickLeft"
  />
</template>
<script setup>
import { useRouter } from "vue-router";
import { reactive, watch, computed } from "vue";
const router = useRouter();
const state = reactive({
  routeObj: {},
});

// 监听当前路由
watch(
  () => router.currentRoute.value,
  (newValue) => {
    // console.log("newValue", newValue);
    state.routeObj = newValue;
  },
  { immediate: true }
);

const barTitle = computed(() => {
  return state.routeObj.meta.title;
});

const isShowBackArrow = computed(() => {
  return state.routeObj.meta.isTab;
});

const onClickLeft = () => {
  history.back();
};
</script>

3、mine.vue

我的页面

<template>
  <div class="page-container">
    <div class="card">
      <div class="img-wrap">
        <van-image
          round
          fit="cover"
          width="80"
          height="80"
          :src="state.personObj.avatar"
        />
      </div>
      <div class="content">
        <van-cell
          :title="state.personObj.personName"
          value="个人资料"
          :label="state.personObj.roleName"
          is-link
          @click="handleClick"
        />
      </div>
    </div>

    <van-cell-group inset>
      <van-cell title="单元格" value="内容" />
      <van-cell title="单元格" value="内容" label="描述信息" />
    </van-cell-group>
  </div>
</template>
<script setup>
import { useRouter } from "vue-router";
import { personApi } from "@/api/personApi.js";
import { reactive } from "vue";
const router = useRouter();
const state = reactive({
  personObj: {},
});

const handleClick = () => {
  console.log("点击:");
  router.push({
    path: "/mine/info",
    query: {
      id: 1,
    },
  });
};

const getPersonData = () => {
  personApi().then((res) => {
    console.log("个人信息:", res);
    const { code, data } = res;
    if (code == 200) {
      state.personObj = data;
    }
  });
};

getPersonData();
</script>
<style scoped>
.card {
  margin: 15px 30px;
  /* border-radius: 0.05333rem;
  border: 0.01333rem solid #ebeef5; */

  overflow: hidden;
  color: #303133;
  box-shadow: 0 2px 12px 0 rgba (0, 0, 0, 0.1);
  transition: 0.3s;
  padding: 15px 10px;
  display: flex;

  background: var(--van-coupon-background);
  border-radius: var(--van-coupon-radius);
  box-shadow: var(--van-coupon-shadow);
}
.content {
  flex: 1;
}
</style>

4、info.vue

个人详情页

<template>
  <div class="page-container">
    <van-cell-group inset>
      <van-cell title="姓名" :value="state.personInfoObj['personName']" />
      <van-cell title="年龄" :value="state.personInfoObj['age']" />
      <van-cell title="爱好" :value="state.personInfoObj['hobby']" />
      <van-cell title="家庭住址" :value="state.personInfoObj['address']" />
    </van-cell-group>
  </div>
</template>

<script setup>
import { useRoute } from "vue-router";
import { reactive } from "vue";
import { personInfoApi } from "@/api/personApi.js";
const route = useRoute();
const state = reactive({
  queryObj: {},
  personInfoObj: {},
});

state.queryObj = route.query;
console.log("route:", route.query);

const getPersonInfo = () => {
  personInfoApi({ id: state.queryObj.id }).then((res) => {
    console.log("详情:", res);
    const { code, data } = res;
    if (code == 200) {
      state.personInfoObj = data;
    }
  });
};

getPersonInfo();
</script>

5、路由处理

meta.title是顶部的title,meta.isTab 是用来判断是否为tabbar页面,true-表示为tabbar页面,false-表示非tabbar页面

import {
  createRouter,
  createWebHistory,
  createWebHashHistory,
} from "vue-router";

const router = createRouter({
  // history: createWebHistory(import.meta.env.BASE_URL),
  // 解决:无报错,js加载了,但是页面空白(router-view没有渲染任何内容)

  history: createWebHashHistory(),
  routes: [
    {
      path: "/",
      name: "index",
      component: () => import("../views/index.vue"),
      redirect: "/home",
      children: [
        {
          path: "/home",
          name: "home",
          meta: {
            title: "首页",
            isTab: true,
          },
          component: () => import("@/views/home/index.vue"),
        },
        {
          path: "/video",
          name: "video",
          meta: {
            title: "视频",
            isTab: true,
          },
          component: () => import("../views/video/index.vue"),
        },
        {
          path: "/mine",
          name: "mine",
          meta: {
            title: "我的",
            isTab: true,
          },
          component: () => import("../components/myRouterView.vue"),
          redirect: "/mine/list",
          children: [
            {
              path: "/mine/list",
              name: "personalList",
              meta: {
                title: "我的",
                isTab: true,
              },
              component: () => import("../views/mine/index.vue"),
            },
            {
              path: "/mine/info",
              name: "personalInfo",
              meta: {
                title: "个人资料",
                isTab: false,
              },
              component: () => import("../views/personalInfo/index.vue"),
            },
          ],
        },
        {
          path: "/goodList",
          name: "goodList",
          meta: {
            title: "商品列表",
            isTab: false,
          },
          component: () => import("../views/goodManage/goodList/index.vue"),
        },
        {
          path: "/goodInfo",
          name: "goodInfo",
          meta: {
            title: "商品详情",
            isTab: false,
          },
          component: () => import("../views/goodManage/goodDetail/index.vue"),
        },
      ],
    },
  ],
});

export default router;

二、运行效果

经过如上的处理,非tabbar页面则可以不展示tab组件,而tabbar页面展示,运行效果如下图所示:

图一   展示tabbar

 

图二  不展示tabbar 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue3可以通过自定义组件实现底部导航栏的灵活组件。以下是一个简单的实现示例: 1. 创建一个TabBar组件,用于展示底部导航栏: ```vue <template> <div class="tab-bar"> <slot></slot> </div> </template> <script> export default { name: "TabBar", }; </script> <style scoped> .tab-bar { display: flex; justify-content: space-around; align-items: center; position: fixed; bottom: 0; left: 0; right: 0; height: 50px; background-color: #fff; box-shadow: 0 -3px 5px rgba(0, 0, 0, 0.1); } </style> ``` 2. 在TabBar组件使用slot插槽,用于接收底部导航栏的子组件。例如: ```vue <template> <div class="tab-bar"> <slot></slot> </div> </template> <script> export default { name: "TabBar", }; </script> <style scoped> .tab-bar { display: flex; justify-content: space-around; align-items: center; position: fixed; bottom: 0; left: 0; right: 0; height: 50px; background-color: #fff; box-shadow: 0 -3px 5px rgba(0, 0, 0, 0.1); } </style> ``` 3. 创建底部导航栏子组件,例如TabBarItem。在TabBarItem可以定义图标、文字和点击事件等属性。例如: ```vue <template> <div class="tab-bar-item" :class="{ active: active }" @click="handleClick"> <i :class="icon"></i> <span>{{ title }}</span> </div> </template> <script> export default { name: "TabBarItem", props: { icon: { type: String, required: true, }, title: { type: String, required: true, }, active: { type: Boolean, required: true, }, }, methods: { handleClick() { this.$emit("click"); }, }, }; </script> <style scoped> .tab-bar-item { display: flex; flex-direction: column; align-items: center; font-size: 12px; color: #666; } .tab-bar-item i { font-size: 20px; margin-bottom: 2px; } .tab-bar-item.active { color: #007aff; } </style> ``` 4. 在父组件使用TabBarTabBarItem组件。例如: ```vue <template> <div> <router-view /> <TabBar> <TabBarItem v-for="(tab, index) in tabs" :key="index" :icon="tab.icon" :title="tab.title" :active="index === activeIndex" @click="activeIndex = index" /> </TabBar> </div> </template> <script> import TabBar from "@/components/TabBar.vue"; import TabBarItem from "@/components/TabBarItem.vue"; export default { name: "App", components: { TabBar, TabBarItem, }, data() { return { tabs: [ { icon: "icon-home", title: "首页", }, { icon: "icon-category", title: "分类", }, { icon: "icon-cart", title: "购物车", }, { icon: "icon-person", title: "个人心", }, ], activeIndex: 0, }; }, }; </script> ``` 在父组件使用TabBarTabBarItem组件,通过循环遍历tabs数组,动态生成底部导航栏子组件TabBarItem,并通过activeIndex属性控制当前激活的子组件。当子组件被点击时,通过click事件向父组件发送消息,触发activeIndex的变化,从而实现底部导航栏的切换。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值