当前位置: 首页 > news >正文

uniapp-vue2导航栏全局自动下拉变色

全局自动下拉变色解决方案
雀语文章地址
📖 项目简介
这是一个基于 Vue.js 和 uni-app 的全局自动下拉变色解决方案,通过全局 mixin 实现页面滚动时导航栏的自动颜色变化效果。
✨ 核心特性
● 🎯 全局自动生效:无需在每个页面手动导入,自动为所有页面添加滚动监听
● 🎨 智能颜色变化:根据滚动位置自动调整导航栏背景色和文字颜色
● 📱 跨平台兼容:支持微信小程序、H5、App 等多端
● ⚡ 性能优化:使用节流函数优化滚动事件处理
● 🔧 易于配置:支持自定义颜色配置和触发阈值
🏗️ 项目结构
buddhism/
├── mixins/
│ └── page-scroll-mixin.js # 全局滚动监听 mixin
├── components/
│ └── custom-navbar/
│ └── custom-navbar.vue # 自定义导航栏组件
├── main.js # 全局 mixin 注册
└── pages/
└── basePage/
└── basePage.vue # 示例页面
🚀 快速开始

  1. 安装依赖

  2. 全局配置
    在 main.js 中已经配置了全局 mixin:

import PageScrollMixin from './mixins/page-scroll-mixin.js'// 注册全局 mixin
Vue.mixin(PageScrollMixin)
  1. 使用导航栏组件
    在任何页面中直接使用 custom-navbar 组件:
<template><view class="page"><!-- 自定义导航栏 --><custom-navbar title="页面标题":show-back="true"@back="goBack"ref="customNavbar"//必写/><!-- 页面内容 --><view class="content"><!-- 你的页面内容 --></view></view>
</template>
<script>
export default {name: 'YourPage',methods: {goBack() {uni.navigateBack()}}
}
</script>

📋 核心文件说明

  1. mixins/page-scroll-mixin.js
    全局滚动监听 mixin,为所有页面提供滚动事件处理:
export default {data() {return {scrollTop: 0,navbarOpacity: 0,navbarTextColor: '#000000',navbarBgColor: 'rgba(255, 255, 255, 0)'}},onPageScroll(e) {this.handlePageScroll(e)},methods: {handlePageScroll(e) {// 节流处理滚动事件if (this.scrollTimer) returnthis.scrollTimer = setTimeout(() => {this.scrollTop = e.scrollTopthis.updateNavbarStyle()this.scrollTimer = null}, 16) // 约60fps},updateNavbarStyle() {// 根据滚动位置更新导航栏样式const opacity = Math.min(this.scrollTop / 100, 1)this.navbarOpacity = opacityif (opacity > 0.5) {this.navbarTextColor = '#000000'this.navbarBgColor = `rgba(255, 255, 255, ${opacity})`} else {this.navbarTextColor = '#ffffff'this.navbarBgColor = `rgba(255, 255, 255, ${opacity})`}}}
}
  1. components/custom-navbar/custom-navbar.vue
    自定义导航栏组件,支持动态样式变化:
<template><view class="custom-navbar":style="navbarStyle"><view class="navbar-content"><view v-if="showBack" class="back-btn"@click="handleBack"><text class="back-icon"></text></view><text class="navbar-title":style="{ color: navbarTextColor }">{{ title }}</text></view></view>
</template>
<script>
export default {name: 'CustomNavbar',props: {title: {type: String,default: ''},showBack: {type: Boolean,default: false}},computed: {navbarStyle() {return {backgroundColor: this.navbarBgColor,color: this.navbarTextColor}}},methods: {handleBack() {this.$emit('back')}}
}
</script>

🎨 自定义配置
修改颜色配置
在 mixins/page-scroll-mixin.js 中可以自定义颜色:

updateNavbarStyle() {const opacity = Math.min(this.scrollTop / 100, 1)this.navbarOpacity = opacity// 自定义颜色逻辑if (opacity > 0.5) {this.navbarTextColor = '#333333'  // 深色文字this.navbarBgColor = `rgba(255, 255, 255, ${opacity})`} else {this.navbarTextColor = '#ffffff'  // 白色文字this.navbarBgColor = `rgba(0, 0, 0, ${opacity * 0.3})`}
}

修改触发阈值
调整滚动距离阈值:


// 将 100 改为你想要的阈值
const opacity = Math.min(this.scrollTop / 50, 1)  // 50px 开始变化

📱 使用示例
基础页面

<template><view class="page"><custom-navbar title="首页":show-back="false"ref="customNavbar"//必写/><view class="content"><view class="banner"><image src="/static/banner.jpg" mode="aspectFill" /></view><view class="list"><view v-for="item in 20" :key="item"class="list-item">列表项 {{ item }}</view></view></view></view>
</template>
<script>
export default {name: 'HomePage'
}
</script>
<style scoped>
.page {min-height: 100vh;background: #f5f5f5;
}.content {padding-top: 44px; /* 导航栏高度 */
}.banner {height: 200px;background: linear-gradient(45deg, #667eea, #764ba2);
}.list-item {padding: 15px;margin: 10px;background: white;border-radius: 8px;box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
</style>详情页面
<template><view class="page"><custom-navbar title="详情页":show-back="true"@back="goBack"/><view class="content"><view class="hero-image"><image src="/static/detail.jpg" mode="aspectFill" /></view><view class="detail-content"><text class="title">详情标题</text><text class="description">详情描述内容...</text></view></view></view>
</template>
<script>
export default {name: 'DetailPage',methods: {goBack() {uni.navigateBack()}}
}
</script>

🔧 技术实现
核心原理

  1. 全局 Mixin:通过 Vue 的全局 mixin 机制,为所有页面自动注入滚动监听
  2. 节流优化:使用 setTimeout 实现 60fps 的滚动事件节流
  3. 动态样式:根据滚动位置计算透明度,实现平滑的颜色过渡
  4. 响应式数据:通过 Vue 的响应式系统,自动更新导航栏样式
    性能优化
    ● ✅ 滚动事件节流(16ms 间隔)
    ● ✅ 使用 computed 属性缓存样式计算
    ● ✅ 避免频繁的 DOM 操作
    ● ✅ 合理的内存管理
    🐛 常见问题
    Q: 导航栏不显示?
    A: 确保页面内容有足够的高度可以滚动,并且设置了正确的 padding-top
    Q: 颜色变化不明显?
    A: 检查背景图片的对比度,可以调整颜色配置或透明度
    Q: 在某些页面不需要效果?
    A: 可以在特定页面中覆盖 mixin 的方法:
    export default {
    onPageScroll() {
    // 覆盖全局 mixin,不执行滚动处理
    }
    }

🤝 贡献
欢迎提交 Issue 和 Pull Request!

注意:此解决方案专为 uni-app 项目设计,确保在目标平台上测试兼容性。

全局导航栏组件,自动实现下拉透明到纯色

import PageScrollMixin from './mixins/page-scroll-mixin.js'// 注册全局 mixin
Vue.mixin(PageScrollMixin)
/*** 页面滚动监听 Mixin* 用于自动处理 custom-navbar 组件的滚动事件传递* * 使用方法:* 1. 在页面中引入此 mixin* 2. 确保 custom-navbar 组件有 ref="customNavbar"(默认)或自定义 ref* 3. 自动处理滚动事件传递* * 配置选项:* - scrollRefs: 需要传递滚动事件的组件 ref 数组,默认为 ['customNavbar']* * 使用示例:* * // 基础用法(使用默认 ref="customNavbar")* export default {*   mixins: [PageScrollMixin],*   // ... 其他配置* }* * // 自定义 ref 名称* export default {*   mixins: [PageScrollMixin],*   scrollRefs: ['myNavbar'], // 自定义 ref 名称*   // ... 其他配置* }* * // 多个组件* export default {*   mixins: [PageScrollMixin],*   scrollRefs: ['customNavbar', 'floatingButton'], // 多个组件*   // ... 其他配置* }*/export default {data() {return {// 默认的滚动组件 ref 列表scrollRefs: this.$options.scrollRefs || ['customNavbar']};},// 页面生命周期onPageScroll(e) {// 自动将页面滚动事件传递给所有配置的组件this.scrollRefs.forEach(refName => {if (this.$refs[refName] && typeof this.$refs[refName].handlePageScroll === 'function') {this.$refs[refName].handlePageScroll(e);}});}
};
<template><view><!-- 填充区,避免内容被导航栏遮挡 --><view class="navbar-placeholder" :style="{ height: navBarHeight + 'px' }"></view><!-- 自定义导航栏 --><view class="custom-navbar" :class="{ 'navbar-scrolled': isScrolled }":style="{ paddingTop: statusBarHeight + 'px', height: navBarHeight + 'px',backgroundColor: isScrolled ? backgroundColor : 'transparent'}"><view class="navbar-left" @click="handleBack" :style="{ height: capsuleHeight + 'px', lineHeight: capsuleHeight + 'px' }"><image :src="backIcon" mode="aspectFit" class="back-icon"></image></view><view class="navbar-title" :style="{ height: capsuleHeight + 'px', lineHeight: capsuleHeight + 'px' }">{{ title }}</view><view class="navbar-right" :style="{ height: capsuleHeight + 'px', lineHeight: capsuleHeight + 'px' }"><slot name="right"></slot></view></view></view>
</template><script>
import CommonEnum from "../../enum/common";export default {name: 'CustomNavbar',props: {title: {type: String,default: ''},backIcon: {type: String,default: CommonEnum.BACK_BUTTON},showBack: {type: Boolean,default: true},// 新增:滚动相关配置backgroundColor: {type: String,default: CommonEnum.BASE_COLOR // 滚动时的背景色,使用基调颜色},scrollThreshold: {type: Number,default: 20 // 滚动阈值,超过此值开始变色},enableScrollEffect: {type: Boolean,default: true // 是否启用滚动效果}},data() {return {statusBarHeight: 0,navBarHeight: 0,menuButtonInfo: null,capsuleHeight: 0,// 新增:滚动状态isScrolled: false,scrollTop: 0,lastScrollTop: 0}},mounted() {this.getSystemInfo();},methods: {getSystemInfo() {// 获取系统信息const systemInfo = uni.getSystemInfoSync();// 获取状态栏高度this.statusBarHeight = systemInfo.statusBarHeight;// 获取胶囊按钮信息this.menuButtonInfo = uni.getMenuButtonBoundingClientRect();// 计算胶囊高度this.capsuleHeight = this.menuButtonInfo.height;// 计算导航栏高度(胶囊底部到状态栏顶部的距离)this.navBarHeight = this.menuButtonInfo.bottom + 8;},handleBack() {if (this.showBack) {// 先触发自定义事件,让父组件有机会处理this.$emit('back');// 自动执行返回逻辑uni.navigateBack({delta: 1});}},// 新增:处理页面滚动(供父组件调用)handlePageScroll(e) {if (!this.enableScrollEffect) return;this.scrollTop = e.scrollTop;// 判断是否超过滚动阈值if (this.scrollTop > this.scrollThreshold) {if (!this.isScrolled) {this.isScrolled = true;this.$emit('scroll-change', { isScrolled: true, scrollTop: this.scrollTop });}} else {if (this.isScrolled) {this.isScrolled = false;this.$emit('scroll-change', { isScrolled: false, scrollTop: this.scrollTop });}}// 触发滚动事件,让父组件可以获取滚动信息this.$emit('scroll', {scrollTop: this.scrollTop,isScrolled: this.isScrolled});},// 新增:手动设置滚动状态(供父组件调用)setScrollState(scrollTop) {if (!this.enableScrollEffect) return;this.scrollTop = scrollTop;this.isScrolled = scrollTop > this.scrollThreshold;}}
}
</script><style lang="scss" scoped>
/* 填充区样式 */
.navbar-placeholder {width: 100%;background-color: transparent;
}/* 自定义导航栏样式 */
.custom-navbar {position: fixed;top: 0;left: 0;right: 0;z-index: 999;padding-top: 0;background-color: transparent;display: flex;align-items: center;justify-content: space-between;padding-left: 30rpx;padding-right: 30rpx;box-sizing: border-box;transition: background-color 0.3s ease; /* 添加过渡动画 */
}/* 滚动状态样式 */
.navbar-scrolled {box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1); /* 滚动时添加阴影 */
}.navbar-left {display: flex;align-items: center;justify-content: center;width: 60rpx;.back-icon {width: 56rpx;height: 56rpx;}
}.navbar-title {font-size: 36rpx;font-weight: bold;color: #695347;flex: 1;text-align: center;display: flex;align-items: center;justify-content: center;
}.navbar-right {width: 60rpx;display: flex;align-items: center;justify-content: center;
}
</style>
<template><view class="page"><custom-navbarref="customNavbar"title="基础页面"/><tile-grid/><view class="header" :style="{ backgroundColor: CommonEnum.BASE_COLOR }"><!-- 状态展示 --><status-displayv-if="loading"type="loading"loading-text="加载中..."/><!-- 页面内容将在这里添加 --></view></view>
</template><script>
import CommonEnum from "../../enum/common";
import StatusDisplay from "../../components/status-display/status-display.vue";export default {components: {StatusDisplay},data() {return {CommonEnum,loading: false}},onLoad() {// 页面加载时获取数据this.loadPageData()},methods: {// 加载页面数据async loadPageData() {this.loading = truetry {// TODO: 调用页面数据API// const response = await getPageData()// 模拟加载setTimeout(() => {this.loading = false}, 1000)} catch (error) {console.error('获取页面数据失败:', error)this.loading = false}}}
}
</script><style lang="scss" scoped>
.page {background: #F5F0E7;
}
.header {width: 100%;min-height: 100vh;display: flex;align-items: flex-start;flex-direction: column;padding: 0 15rpx;padding-bottom: 40rpx;
}
</style>

颜色是在枚举中是 #FFFFFF
图片都是 网络地址

雀语文章地址

http://www.dtcms.com/a/320186.html

相关文章:

  • 损耗对信号质量的影响
  • OpenAI 开源 GPT-OSS:大型语言模型的开放时代正式来临!
  • HTTP请求头详解:从基础到实战
  • 当函数返回有多个返回值时,需要注意的问题 : Effective Python 第19条
  • C++ vector 扩容时到底发生了什么?
  • 一个程序通过 HTTP 协议调用天气 API,解析 JSON 格式的天气数据,提取关键信息并格式化输出:日期、天气状况、温度范围、风向、湿度等核心气象数据。
  • 1688 商品详情接口开发实战:从平台特性到高可用实现
  • Redis最新安装教程(WindowsLinux)
  • 对基带信号进行调制的原因及通俗理解
  • HR人才测评工具,卡特尔16pf性格测试
  • Numpy科学计算与数据分析:Numpy数学函数入门与实践
  • 我爱发明之Linux下使用Conky在桌面显示Spotify状态及封面字符画
  • 无损音乐下载器!(电脑)绿色免费,无限下载,无损音质
  • 是否将标签页tag信息存储在Redux store中还是仅存储在hook的state中
  • AI题解5
  • 什么是0.5米分辨率卫星影像数据?
  • 一文学会c++继承 组合
  • [优选算法专题一双指针——两数之和](双指针和哈希表)
  • 解决GitHub push失败-Failed to connect to github.com port 443: Timed out
  • 亚马逊卖家反馈机制变革:纯星级评级时代的合规挑战与运营重构
  • SOMGAN:用自组织映射改善GAN的模式探索能力
  • 自然语言处理×第四卷:文本特征与数据——她开始准备:每一次输入,都是为了更像你地说话
  • python selenium环境安装
  • Python自动化测试selenium指定截图文件名方法
  • MySQL 备份利器 Xtrabackup 全解析:从部署到恢复的实战指南
  • 视觉语言模型的空间推理缺陷——AI 在医学扫描中难以区分左右
  • 《CogAgent: A Visual Language Model for GUI Agents》论文精读笔记
  • Vue 3 入门教程 9 - 表单处理
  • 8、Redis的HyperLogLog、事务Multi、管道Pipeline,以及Redis7.0特性
  • DoubleTrouble靶机