370 lines
7.4 KiB
Markdown
370 lines
7.4 KiB
Markdown
|
|
# 全局自动下拉变色解决方案
|
|||
|
|
|
|||
|
|
## 📖 项目简介
|
|||
|
|
|
|||
|
|
这是一个基于 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. 安装依赖
|
|||
|
|
|
|||
|
|
确保项目已安装以下依赖:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
npm install uview-ui
|
|||
|
|
npm install weapp-cookie
|
|||
|
|
npm install js-md5
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 全局配置
|
|||
|
|
|
|||
|
|
在 `main.js` 中已经配置了全局 mixin:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
import PageScrollMixin from './mixins/page-scroll-mixin.js'
|
|||
|
|
|
|||
|
|
// 注册全局 mixin
|
|||
|
|
Vue.mixin(PageScrollMixin)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 使用导航栏组件
|
|||
|
|
|
|||
|
|
在任何页面中直接使用 `custom-navbar` 组件:
|
|||
|
|
|
|||
|
|
```vue
|
|||
|
|
<template>
|
|||
|
|
<view class="page">
|
|||
|
|
<!-- 自定义导航栏 -->
|
|||
|
|
<custom-navbar
|
|||
|
|
title="页面标题"
|
|||
|
|
:show-back="true"
|
|||
|
|
@back="goBack"
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
<!-- 页面内容 -->
|
|||
|
|
<view class="content">
|
|||
|
|
<!-- 你的页面内容 -->
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
export default {
|
|||
|
|
name: 'YourPage',
|
|||
|
|
methods: {
|
|||
|
|
goBack() {
|
|||
|
|
uni.navigateBack()
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 📋 核心文件说明
|
|||
|
|
|
|||
|
|
### 1. `mixins/page-scroll-mixin.js`
|
|||
|
|
|
|||
|
|
全局滚动监听 mixin,为所有页面提供滚动事件处理:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
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) return
|
|||
|
|
|
|||
|
|
this.scrollTimer = setTimeout(() => {
|
|||
|
|
this.scrollTop = e.scrollTop
|
|||
|
|
this.updateNavbarStyle()
|
|||
|
|
this.scrollTimer = null
|
|||
|
|
}, 16) // 约60fps
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
updateNavbarStyle() {
|
|||
|
|
// 根据滚动位置更新导航栏样式
|
|||
|
|
const opacity = Math.min(this.scrollTop / 100, 1)
|
|||
|
|
this.navbarOpacity = opacity
|
|||
|
|
|
|||
|
|
if (opacity > 0.5) {
|
|||
|
|
this.navbarTextColor = '#000000'
|
|||
|
|
this.navbarBgColor = `rgba(255, 255, 255, ${opacity})`
|
|||
|
|
} else {
|
|||
|
|
this.navbarTextColor = '#ffffff'
|
|||
|
|
this.navbarBgColor = `rgba(255, 255, 255, ${opacity})`
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. `components/custom-navbar/custom-navbar.vue`
|
|||
|
|
|
|||
|
|
自定义导航栏组件,支持动态样式变化:
|
|||
|
|
|
|||
|
|
```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` 中可以自定义颜色:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
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})`
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 修改触发阈值
|
|||
|
|
|
|||
|
|
调整滚动距离阈值:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
// 将 100 改为你想要的阈值
|
|||
|
|
const opacity = Math.min(this.scrollTop / 50, 1) // 50px 开始变化
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 📱 使用示例
|
|||
|
|
|
|||
|
|
### 基础页面
|
|||
|
|
|
|||
|
|
```vue
|
|||
|
|
<template>
|
|||
|
|
<view class="page">
|
|||
|
|
<custom-navbar
|
|||
|
|
title="首页"
|
|||
|
|
:show-back="false"
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
<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>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 详情页面
|
|||
|
|
|
|||
|
|
```vue
|
|||
|
|
<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 的方法:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
export default {
|
|||
|
|
onPageScroll() {
|
|||
|
|
// 覆盖全局 mixin,不执行滚动处理
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 📄 许可证
|
|||
|
|
|
|||
|
|
MIT License
|
|||
|
|
|
|||
|
|
## 🤝 贡献
|
|||
|
|
|
|||
|
|
欢迎提交 Issue 和 Pull Request!
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**注意**:此解决方案专为 uni-app 项目设计,确保在目标平台上测试兼容性。
|