vue3uniapp实现自定义拱形底部导航栏,解决首次闪烁问题

news2024/11/5 19:43:03

前言:

        我最初在网上翻阅查找了很多方法,发现大家都是说在page.json中tabbar中添加:"custom": true,即可解决首次闪烁的问题,可是添加了我这边还是会闪烁,因此我这边改变了思路,使用了虚拟页面来解决此问题。

效果图:

一:编写

       1. 在page.json中写一个初始页面,pages中的第一个对象是默认展示第一个页面,所以一定要在写一个。

  "pages": [
        {
            "name": "index",
            "path": "pages/index/index",
            "style":{
                "navigationStyle":"custom"
            }
        },

        2.新建index文件

        3.编写index文件,因为我有三个页面,底部会有三个选项,每一个组件对应一个页面,Tabbr是我自定义的底部导航栏

    <view>
        <view>
            <view v-if="pageStatus[0]" class="page__container" :style="pageContainerStyle(0)">
                <scroll-view class="scroll-view" scroll-y>
                    <BasicPage />
                </scroll-view>
            </view>
            <view v-if="pageStatus[1]" class="page__container" :style="pageContainerStyle(1)">
                <scroll-view class="scroll-view" scroll-y>
                    <InquiriesPage />
                </scroll-view>
            </view>
            <view v-if="pageStatus[2]" class="page__container" :style="pageContainerStyle(2)">
                <scroll-view class="scroll-view" scroll-y>
                    <user />
                </scroll-view>
            </view>
        </view>
        //自定义底部组件,后面会讲怎么写
        <Tabbr :current-page="0" @change="change"></Tabbr>
    </view>

        4.编写自定义导航栏,可以直接复制,修改路径为自己文件路径

<template>
    <view class="tabbar-home">
        <!-- 拱形区域 -->
        <view class="arched"></view>
        <view class="arched-bg"></view>
        <!-- 盒子 -->
        <view class="tabbar-container">
            <view class="tabbar-item" v-for="(item, index) in tabbarList" :class="[item.centerItem ? ' center-item' : '']" @click="changeItem(item)">
                <view class="item-top">
                    <image :src="currentItem == item.id ? item.selectIcon : item.icon"></image>
                </view>
                <view class="item-bottom" :class="[currentItem == item.id ? 'item-active' : '']">
                    <text>{{ item.text }}</text>
                </view>
            </view>
        </view>
    </view>
</template>
<script setup>
import { defineProps, onMounted, ref } from 'vue'
const props = defineProps({
    currentPage: {
        type: Number,
        default: 0,
    },
})
const currentItem = ref(0)
const tabbarList = ref([
    {
        id: 0,
        path: '/pages/home/index',
        icon: '/static/images/tabBar/unhome.png',
        selectIcon: '/static/images/tabBar/homeSelect.png',
        text: '首页',
        centerItem: false,
    },
    {
        id: 1,
        path: '/pages/detail/index',
        icon: '/static/images/tabBar/unInquiries.png',
        selectIcon: '/static/images/tabBar/Inquiries.png',
        text: '问询',
        centerItem: true,
    },
    {
        id: 2,
        path: '/pages/user/index',
        icon: '/static/images/tabBar/unhome.png',
        selectIcon: '/static/images/tabBar/homeSelect.png',
        text: '我的',
        centerItem: false,
    },
])
const emit = defineEmits(['change'])
function changeItem(item) {
    currentItem.value = item.id
    emit('change', item)
    // uni.switchTab({
    //     url: item.path,
    // })
}

onMounted(() => {
    currentItem.value = props.currentPage
    // 非微信小程序需隐藏原生tabBar(微信小程序已通过"custom": true配置项隐藏原生tabbar)
    if (process.env.VUE_APP_PLATFORM != 'mp-weixin') {
        uni.hideTabBar()
    }
})
</script>

<style lang="scss" scoped>
.tabbar-home {
    z-index: 20090;
    height: 100rpx;
    position: fixed;
    left: 0;
    bottom: 0;
    box-shadow: 0rpx 0rpx 30rpx 0rpx rgba(0, 0, 0, 0.07);
    width: 100%;
    box-sizing: content-box;
    padding-bottom: env(safe-area-inset-bottom) !important;
}
view {
    padding: 0;
    margin: 0;
    box-sizing: border-box;
}

.tabbar-container {
    position: absolute;
    bottom: 0rpx;
    left: 50%;
    transform: translateX(-50%);
    width: 100%;
    /* box-shadow: 0 0 5px    #8d6c36; */
    display: flex;
    align-items: center;
    justify-content: space-around;
    padding: 5rpx 0;
    color: #8d6c36;
    height: 100%;
    padding-bottom: env(safe-area-inset-bottom) !important;
    box-shadow: 0rpx 0rpx 30rpx 0rpx rgba(0, 0, 0, 0.07);
    background-color: rgba(255, 255, 255, 1);
    z-index: inherit;
}

.tabbar-container .tabbar-item {
    width: 20%;
    height: 80rpx;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    text-align: center;
}

.tabbar-container .item-active {
    color: #01beff;
}

.tabbar-container .center-item {
    display: block;
    position: relative;
    margin-top: 20rpx;
}

.tabbar-container .tabbar-item .item-top {
    width: 70rpx;
    height: 70rpx;
    padding: 10rpx;
    background: #ffffff;
}

.tabbar-container .center-item .item-top {
    flex-shrink: 0;
    width: 100%;
    height: 140rpx;
    padding: 20rpx;
    position: absolute;
    top: -70rpx;
    /* left: calc(50% - 50rpx); */
    border-radius: 50%;
    /* box-shadow: 0 0 5px #999; */
    // background-color: #f3d9a6;
}

.tabbar-container .tabbar-item .item-top image {
    width: 40rpx;
    height: 40rpx;
}

.tabbar-container .center-item .item-top image {
    width: 70rpx;
    height: 70rpx;
}

.tabbar-container .tabbar-item .item-bottom {
    font-size: 28rpx;
    width: 100%;
}

.tabbar-container .center-item .item-bottom {
    position: absolute;
    bottom: 0;
}
.arched {
    width: 120rpx;
    height: 120rpx;
    left: 50%;
    top: -42rpx;

    position: absolute;
    transform: translateX(-50%);
    border-radius: 50%;
    box-shadow: 0rpx 0rpx 30rpx 0rpx rgba(0, 0, 0, 0.07);
    background-color: rgba(255, 255, 255, 1);
    // border: 2rpx solid rgba(0, 0, 0, 0.1);
    z-index: 20089;
}
.arched-bg {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    z-index: 20089;
    background-color: rgba(255, 255, 255, 1);
}
</style>

5.在index文件中引入了自定义导航栏组件和各页面组件

<script setup lang="ts">
import Tabbr from '../Tabbar/index.vue'
import BasicPage from './sub-page/BasicPage/index.vue'
import InquiriesPage from './sub-page/Inquiries/index.vue'
import user from './sub-page/user/index.vue'
import { useOrderedChildren } from './sub-page/hooks'
const { children: items, addChild: addItem, removeChild: removeItem } = useOrderedChildren<any>()
const tabbarData = ref([
    {
        id: 0,
        path: '/pages/home/index',
        icon: '/static/images/tabBar/unhome.png',
        selectIcon: '/static/images/tabBar/homeSelect.png',
        text: '首页',
        centerItem: false,
    },
    {
        id: 1,
        path: '/pages/detail/index',
        icon: '/static/images/tabBar/unhome.png',
        selectIcon: '/static/images/tabBar/homeSelect.png',
        text: '问询',
        centerItem: true,
    },
    {
        id: 2,
        path: '/pages/user/index',
        icon: '/static/images/tabBar/unhome.png',
        selectIcon: '/static/images/tabBar/homeSelect.png',
        text: '我的',
        centerItem: false,
    },
])

// 记录每个子页面的状态
const pageStatus = ref(Array.from({ length: tabbarData.value.length }, () => false))
const currentIndex = ref(0)
const change = (item: any) => {
    pageStatus.value = pageStatus.value.map(() => false)
    if (!pageStatus.value?.[item.id as number]) {
        pageStatus.value[item.id as number] = true
        currentIndex.value = item.id
        nextTick(() => {
            items.value?.[item.id as number]?.onLoad?.()
        })
    }
}
const pageContainerStyle = computed<(index: number) => any>(() => {
    console.log('currentIndex', currentIndex.value)
    return (index: number) => {
        const style: any = {}

        if (index !== currentIndex.value) {
            style.display = 'none'
        }

        return style
    }
})
onLoad((options) => {
    const index = Number(options?.index || 0)
    pageStatus.value[index] = true
    nextTick(() => {
        currentIndex.value = index
    })
})
</script>

6.对了提个醒,自定义导航栏组件要写在page文件中~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2231075.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软考系统分析师知识点三一:案例知识点二

前言 今年报考了11月份的软考高级&#xff1a;系统分析师。 考试时间&#xff1a;11月9日。 倒计时&#xff1a;6天。 目标&#xff1a;优先应试&#xff0c;其次学习&#xff0c;再次实践。 复习计划第三阶段&#xff1a;总结案例知识点&#xff0c;并作为论文的框架知识…

WorkFlow源码剖析——Communicator之TCPServer(上)

WorkFlow源码剖析——Communicator之TCPServer&#xff08;上&#xff09; 前言 上一篇博客已经介绍了一下WorkFlow GO-Task的实现原理。本文会介绍一下WorkFlow Tcp Server端的一些实现细节以及有趣的思想。因为这部分涉及的内容有点多&#xff0c;一些有趣的细节也希望能完…

嵌入式硬件电子电路设计(一)开关电源Buck电路

目录 Buck电路基本结构 1. 开关闭合&#xff08;SW 闭合&#xff09; 2. 开关断开&#xff08;SW 断开&#xff09; 3. 开关控制和占空比 MP1584电路分析 其他Buck芯片的电路参考 Buck电路基本结构 下图是简化之后的BUCK电路主回路。下面分析输出电压的产生K闭合后&…

UE4_Niagara基础实例—13、通过纹理采样来创造粒子

效果&#xff1a; 知识点&#xff1a; 1、纹理采样目前仅支持GPU粒子运行&#xff08;Texture sampling is only supported on the GPU at the moment.&#xff09; 2、网格位置输出每个粒子在网格中的归一化位置。我们使用该值来采样纹理&#xff0c;就像它是UV一样&#xff…

多个锚点定位时的锚点优选方法(附公式和python代码讲解)

以下是将上述 MATLAB 代码转化为 Python 代码的版本。我们使用 NumPy 库进行数值计算&#xff0c;并使用 itertools 库生成锚点组合。 1. 基于几何分布的选择 锚点的几何分布影响定位的可辨识性。选择位置均匀分布的锚点组合可以提高定位精度。具体来说&#xff0c;锚点之间的…

HTML 基础概念:什么是 HTML ? HTML 的构成 与 HTML 基本文档结构

文章目录 什么是 HTML &#xff1f;HTML 的构成 &#xff1f;什么是 HTML 元素&#xff1f;HTML 元素的组成部分HTML 元素的特点 HTML 基本文档结构如何打开新建的 HTML 文件代码查看 什么是 HTML &#xff1f; HTML&#xff08;超文本标记语言&#xff0c;HyperText Markup L…

web安全测试渗透案例知识点总结(上)——小白入狱

目录 一、Web安全渗透测试概念详解1. Web安全与渗透测试2. Web安全的主要攻击面与漏洞类型3. 渗透测试的基本流程 二、知识点详细总结1. 常见Web漏洞分析2. 渗透测试常用工具及其功能 三、具体案例教程案例1&#xff1a;SQL注入漏洞利用教程案例2&#xff1a;跨站脚本&#xff…

基于Qt的独立线程创建与多线程执行实验Demo

一、多线程与线程池的应用目的[1][4] &#xff08;一&#xff09;多线程 一个进程内多个线程并发执行的情况就叫多线程&#xff0c;每一个线程是一个独立的执行流。多线程是一种编程模型&#xff0c;它与处理器无关&#xff0c;与设计机制有关。 需要多线程的原因包括&#xf…

基于FPGA的图像双线性插值算法verilog实现,包括tb测试文件和MATLAB辅助验证

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 这里实现的是256*256双线性插值到512*512的系统模块 局部放大&#xff1a; 将数据导入到matlab&#xff0c;得到插值效果…

Spring1(初始Spring 解耦实现 SpringIOC SpringDI Spring常见面试题)

Spring1 创建项目集成maven创建一个Maven项目实现&#xff1a; 初识SpringSpring简介Spring的发展历史Spring之父体系结构生态系统官方文档解耦实现JDBCSpringBoot整合MyBatis和lombok&#xff0c;开启驼峰映射三层思想 SpringIOC实现 SpringDIset注入全部代码&#xff1a;实现…

纯享受 : 力扣:234 回文链表

BLG牛逼 – 奖励自己一道题 描述&#xff1a; 给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为 回文链表 。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例&#xff1a; 何解&#xff1f; 1、所谓 回文 就是正读反读都一样&…

开源项目-投票管理系统

哈喽,大家好,今天主要给大家带来一个开源项目-投票管理系统 投票管理系统主要有首页,发起投票,管理投票,参与投票,查看投票等功能 首页 为用户提供了一键导航到各个功能模块的便捷途径。 新增投票 用户可以在此轻松创建新的投票活动,设置投票主题、选项等信息。 管理…

系统架构图设计(行业领域架构)

物联网 感知层&#xff1a;主要功能是感知和收集信息。感知层通过各种传感器、RFID标签等设备来识别物体、采集信息&#xff0c;并对这些信息进行初步处理。这一层的作用是实现对物理世界的感知和初步处理&#xff0c;为上层提供数据基础网络层&#xff1a;网络层负责处理和传输…

APP获取用户的三大法则

APP内容&#xff0c;提升APP吸引力和用户留存率 A. 用户研究深化 1. **深入用户行为分析**&#xff1a; - 用户使用路径分析 - 用户行为模式识别 - 用户流失点分析 2. **定性研究与定量研究结合**&#xff1a; - 进行深度访谈和焦点小组讨论 - 利用数据分析用…

QT——串口调试助手

目录 1.QSerialPort类包含了很多有关串口的API 2.实现串口的打开 2.1 方法一&#xff1a;通过函数实现 2.2 方法二&#xff1a;在ui界面右下角实现 3. 实现定时发送 3.1类的私有成员中添加定时器QTimer timer并去构造函数中初始化它 3.2帮助文档中有QTimer类相关的说明 …

全自动一键批量创建站群网站插件 | Z-BlogPHP 堆词起站工具

在当今竞争激烈的数字营销世界&#xff0c;如何快速提升网站曝光率和流量&#xff1f;答案就是智能站群系统。 本文将结合实际效果&#xff0c;介绍一款功能强大的站群系统&#xff0c;重点讲述其堆词功能、泛目录管理、一键批量创建、内容转码、自定义标签和GPT内容生成与发布…

计算机毕业设计Spark+大模型知识图谱中药推荐系统 中药数据分析可视化大屏 中药爬虫 机器学习 中药预测系统 中药情感分析 大数据毕业设计

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

Linux云计算 |【第五阶段】CLOUD-DAY7

主要内容&#xff1a; 在kubernetes平台上理解掌握各种控制器的用法&#xff1a;掌握kubectl管理命令、掌握POD原理、掌握集群调度的规则、熟悉控制器资源文件&#xff1b; 一、kubectl 常用命令 Kubectl是用于控制Kubernetes集群的命令行工具&#xff1b; - 格式&#xff1…

json-server的使用(根据json数据一键生成接口)

一.使用目的 在前端开发初期&#xff0c;后端 API 可能还未完成&#xff0c;json-server 可以快速创建模拟的 RESTful API&#xff0c;帮助前端开发者进行开发和测试。 二.安装 npm install json-server //局部安装npm i json-server -g //全局安装 三.使用教程 1.准备一…

在VS中安装chatGPT

2、在VSCode中打开插件窗口 3、输入ChatGPT 4、这里有个ChatGPT中文版&#xff0c;就它了 5、安装 6、这时候侧边栏多了一个chatGPT分页图标&#xff0c;点击它 7、打个招呼 8、好像不行 9、看一下细节描述 10、根据要求按下按下快捷键 Ctrl Shift P 11、切换成国内模式 12、…