导航栏组件的自动变色
This commit is contained in:
parent
6916d22815
commit
5e24031199
|
|
@ -1,25 +1,149 @@
|
||||||
# CustomNavbar 自定义导航栏组件
|
# Custom Navbar 组件使用说明
|
||||||
|
|
||||||
## 功能特性
|
## 功能特性
|
||||||
|
|
||||||
- 自动适配微信小程序状态栏高度
|
- 自动监听页面滚动
|
||||||
- 自动计算胶囊按钮高度,确保文字与胶囊水平对齐
|
- 滚动时导航栏变为纯色背景
|
||||||
- 支持自定义标题、返回按钮图标
|
- 回到顶部时导航栏变为透明
|
||||||
- 支持右侧插槽,可添加自定义内容
|
- 支持自定义背景色和滚动阈值
|
||||||
- 支持返回事件回调
|
- 提供滚动状态事件回调
|
||||||
|
|
||||||
## 使用方法
|
## 基本用法
|
||||||
|
|
||||||
### 基础用法
|
|
||||||
|
|
||||||
```vue
|
```vue
|
||||||
<template>
|
<template>
|
||||||
<view class="page">
|
<view>
|
||||||
<custom-navbar title="页面标题" />
|
<custom-navbar title="页面标题" />
|
||||||
<!-- 页面内容,无需设置 margin-top -->
|
<!-- 页面内容 -->
|
||||||
<view class="content">
|
</view>
|
||||||
<text>页面内容</text>
|
</template>
|
||||||
</view>
|
```
|
||||||
|
|
||||||
|
## 高级用法
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<custom-navbar
|
||||||
|
title="古刹巡礼"
|
||||||
|
:backgroundColor="'#FAF8F3'"
|
||||||
|
:scrollThreshold="100"
|
||||||
|
:enableScrollEffect="true"
|
||||||
|
@scroll-change="onScrollChange"
|
||||||
|
@scroll="onScroll"
|
||||||
|
>
|
||||||
|
<template #right>
|
||||||
|
<view class="right-button">更多</view>
|
||||||
|
</template>
|
||||||
|
</custom-navbar>
|
||||||
|
|
||||||
|
<!-- 页面内容 -->
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
onScrollChange(data) {
|
||||||
|
console.log('滚动状态变化:', data.isScrolled);
|
||||||
|
},
|
||||||
|
onScroll(data) {
|
||||||
|
console.log('滚动位置:', data.scrollTop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Props 参数
|
||||||
|
|
||||||
|
| 参数 | 类型 | 默认值 | 说明 |
|
||||||
|
|------|------|--------|------|
|
||||||
|
| title | String | '' | 导航栏标题 |
|
||||||
|
| backIcon | String | CommonEnum.BACK_BUTTON | 返回按钮图标 |
|
||||||
|
| showBack | Boolean | true | 是否显示返回按钮 |
|
||||||
|
| backgroundColor | String | '#ffffff' | 滚动时的背景色 |
|
||||||
|
| scrollThreshold | Number | 50 | 滚动阈值(像素) |
|
||||||
|
| enableScrollEffect | Boolean | true | 是否启用滚动效果 |
|
||||||
|
|
||||||
|
## Events 事件
|
||||||
|
|
||||||
|
| 事件名 | 参数 | 说明 |
|
||||||
|
|--------|------|------|
|
||||||
|
| back | - | 点击返回按钮时触发 |
|
||||||
|
| scroll-change | { isScrolled, scrollTop } | 滚动状态变化时触发 |
|
||||||
|
| scroll | { scrollTop, isScrolled } | 页面滚动时触发 |
|
||||||
|
|
||||||
|
## 方法
|
||||||
|
|
||||||
|
| 方法名 | 参数 | 说明 |
|
||||||
|
|--------|------|------|
|
||||||
|
| setScrollState | scrollTop | 手动设置滚动状态 |
|
||||||
|
|
||||||
|
## 样式定制
|
||||||
|
|
||||||
|
组件会自动添加以下 CSS 类:
|
||||||
|
|
||||||
|
- `.navbar-scrolled`: 滚动状态下的样式
|
||||||
|
- 过渡动画:背景色变化有 0.3s 的过渡效果
|
||||||
|
- 阴影效果:滚动时自动添加阴影
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. **重要**:需要在父页面的 `onPageScroll` 生命周期中调用组件的 `handlePageScroll` 方法
|
||||||
|
2. 滚动效果默认启用,可通过 `enableScrollEffect` 关闭
|
||||||
|
3. 背景色变化有平滑过渡动画
|
||||||
|
4. 组件使用 `ref` 引用,确保在页面中正确引用
|
||||||
|
|
||||||
|
## 完整使用示例
|
||||||
|
|
||||||
|
### 方法一:使用 Mixin(推荐)
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<custom-navbar
|
||||||
|
ref="customNavbar"
|
||||||
|
title="页面标题"
|
||||||
|
backgroundColor="#FAF8F3"
|
||||||
|
:scrollThreshold="50"
|
||||||
|
@scroll-change="onScrollChange"
|
||||||
|
/>
|
||||||
|
<!-- 页面内容 -->
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import CustomNavbar from "@/components/custom-navbar/custom-navbar.vue";
|
||||||
|
import PageScrollMixin from "@/mixins/page-scroll-mixin.js";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [PageScrollMixin], // 自动处理滚动事件
|
||||||
|
components: {
|
||||||
|
CustomNavbar
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onScrollChange(data) {
|
||||||
|
console.log('滚动状态变化:', data.isScrolled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方法二:手动处理
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<custom-navbar
|
||||||
|
ref="customNavbar"
|
||||||
|
title="页面标题"
|
||||||
|
backgroundColor="#FAF8F3"
|
||||||
|
:scrollThreshold="50"
|
||||||
|
@scroll-change="onScrollChange"
|
||||||
|
/>
|
||||||
|
<!-- 页面内容 -->
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -29,64 +153,19 @@ import CustomNavbar from "@/components/custom-navbar/custom-navbar.vue";
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
CustomNavbar
|
CustomNavbar
|
||||||
|
},
|
||||||
|
// 页面生命周期 - 必须添加
|
||||||
|
onPageScroll(e) {
|
||||||
|
// 将页面滚动事件传递给导航栏组件
|
||||||
|
if (this.$refs.customNavbar) {
|
||||||
|
this.$refs.customNavbar.handlePageScroll(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onScrollChange(data) {
|
||||||
|
console.log('滚动状态变化:', data.isScrolled);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
### 自定义返回按钮图标
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<custom-navbar
|
|
||||||
title="页面标题"
|
|
||||||
:backIcon="customBackIcon"
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 隐藏返回按钮
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<custom-navbar
|
|
||||||
title="页面标题"
|
|
||||||
:showBack="false"
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 添加右侧内容
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<custom-navbar title="页面标题">
|
|
||||||
<template #right>
|
|
||||||
<view class="right-content">
|
|
||||||
<text>右侧内容</text>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</custom-navbar>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Props
|
|
||||||
|
|
||||||
| 参数 | 类型 | 默认值 | 说明 |
|
|
||||||
|------|------|--------|------|
|
|
||||||
| title | String | '' | 导航栏标题 |
|
|
||||||
| backIcon | String | CommonEnum.BACK_BUTTON | 返回按钮图标路径 |
|
|
||||||
| showBack | Boolean | true | 是否显示返回按钮 |
|
|
||||||
|
|
||||||
## Events
|
|
||||||
|
|
||||||
| 事件名 | 说明 | 回调参数 |
|
|
||||||
|--------|------|----------|
|
|
||||||
| back | 点击返回按钮时触发(可选,组件会自动执行返回逻辑) | - |
|
|
||||||
|
|
||||||
## Slots
|
|
||||||
|
|
||||||
| 插槽名 | 说明 |
|
|
||||||
|--------|------|
|
|
||||||
| right | 右侧内容插槽 |
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
1. 组件会自动计算状态栏和胶囊高度,无需手动设置
|
|
||||||
2. 组件使用 `position: fixed` 定位,确保在页面顶部
|
|
||||||
3. 组件内部包含填充区,页面内容无需设置 `margin-top`
|
|
||||||
4. 组件样式使用 `scoped`,不会影响其他组件
|
|
||||||
|
|
@ -4,7 +4,15 @@
|
||||||
<view class="navbar-placeholder" :style="{ height: navBarHeight + 'px' }"></view>
|
<view class="navbar-placeholder" :style="{ height: navBarHeight + 'px' }"></view>
|
||||||
|
|
||||||
<!-- 自定义导航栏 -->
|
<!-- 自定义导航栏 -->
|
||||||
<view class="custom-navbar" :style="{ paddingTop: statusBarHeight + 'px', height: navBarHeight + 'px' }">
|
<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' }">
|
<view class="navbar-left" @click="handleBack" :style="{ height: capsuleHeight + 'px', lineHeight: capsuleHeight + 'px' }">
|
||||||
<image :src="backIcon" mode="aspectFit" class="back-icon"></image>
|
<image :src="backIcon" mode="aspectFit" class="back-icon"></image>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -33,6 +41,19 @@ export default {
|
||||||
showBack: {
|
showBack: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
|
},
|
||||||
|
// 新增:滚动相关配置
|
||||||
|
backgroundColor: {
|
||||||
|
type: String,
|
||||||
|
default: CommonEnum.BASE_COLOR // 滚动时的背景色,使用基调颜色
|
||||||
|
},
|
||||||
|
scrollThreshold: {
|
||||||
|
type: Number,
|
||||||
|
default: 20 // 滚动阈值,超过此值开始变色
|
||||||
|
},
|
||||||
|
enableScrollEffect: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true // 是否启用滚动效果
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|
@ -41,6 +62,10 @@ export default {
|
||||||
navBarHeight: 0,
|
navBarHeight: 0,
|
||||||
menuButtonInfo: null,
|
menuButtonInfo: null,
|
||||||
capsuleHeight: 0,
|
capsuleHeight: 0,
|
||||||
|
// 新增:滚动状态
|
||||||
|
isScrolled: false,
|
||||||
|
scrollTop: 0,
|
||||||
|
lastScrollTop: 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
@ -71,6 +96,40 @@ export default {
|
||||||
delta: 1
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -98,6 +157,12 @@ export default {
|
||||||
padding-left: 30rpx;
|
padding-left: 30rpx;
|
||||||
padding-right: 30rpx;
|
padding-right: 30rpx;
|
||||||
box-sizing: border-box;
|
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 {
|
.navbar-left {
|
||||||
|
|
|
||||||
5
main.js
5
main.js
|
|
@ -64,3 +64,8 @@ Vue.prototype.wxLogin = async function(){
|
||||||
|
|
||||||
|
|
||||||
// app.$mount()
|
// app.$mount()
|
||||||
|
|
||||||
|
import PageScrollMixin from './mixins/page-scroll-mixin.js'
|
||||||
|
|
||||||
|
// 注册全局 mixin
|
||||||
|
Vue.mixin(PageScrollMixin)
|
||||||
|
|
|
||||||
53
mixins/page-scroll-mixin.js
Normal file
53
mixins/page-scroll-mixin.js
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
/**
|
||||||
|
* 页面滚动监听 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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="page">
|
<view class="page">
|
||||||
<custom-navbar title="古刹巡礼" />
|
<custom-navbar
|
||||||
|
ref="customNavbar"
|
||||||
|
title="古刹巡礼"
|
||||||
|
/>
|
||||||
<tile-grid/>
|
<tile-grid/>
|
||||||
<scroll-view
|
<scroll-view
|
||||||
class="scroll-container"
|
class="scroll-container"
|
||||||
|
|
@ -61,12 +64,16 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import CommonEnum from "../../enum/common";
|
import CommonEnum from "../../enum/common";
|
||||||
|
import CustomNavbar from "../../components/custom-navbar/custom-navbar.vue";
|
||||||
import StatusDisplay from "../../components/status-display/status-display.vue";
|
import StatusDisplay from "../../components/status-display/status-display.vue";
|
||||||
import AncientItem from "./commponts/ancientItem.vue";
|
import AncientItem from "./commponts/ancientItem.vue";
|
||||||
import { getTempleTours } from "../../api/article/article.js";
|
import { getTempleTours } from "../../api/article/article.js";
|
||||||
|
import PageScrollMixin from "../../mixins/page-scroll-mixin.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
mixins: [PageScrollMixin],
|
||||||
components: {
|
components: {
|
||||||
|
CustomNavbar,
|
||||||
StatusDisplay,
|
StatusDisplay,
|
||||||
'ancient-item': AncientItem
|
'ancient-item': AncientItem
|
||||||
},
|
},
|
||||||
|
|
@ -170,7 +177,8 @@ export default {
|
||||||
this.refreshing = true;
|
this.refreshing = true;
|
||||||
await this.loadPageData();
|
await this.loadPageData();
|
||||||
this.refreshing = false;
|
this.refreshing = false;
|
||||||
}
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="page">
|
<view class="page">
|
||||||
<custom-navbar title="基础页面" />
|
<custom-navbar
|
||||||
|
ref="customNavbar"
|
||||||
|
title="基础页面"
|
||||||
|
/>
|
||||||
<tile-grid/>
|
<tile-grid/>
|
||||||
<view class="header" :style="{ backgroundColor: CommonEnum.BASE_COLOR }">
|
<view class="header" :style="{ backgroundColor: CommonEnum.BASE_COLOR }">
|
||||||
<!-- 状态展示 -->
|
<!-- 状态展示 -->
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
<view class="page">
|
<view class="page">
|
||||||
<base-background />
|
<base-background />
|
||||||
<!-- 使用自定义导航栏组件 -->
|
<!-- 使用自定义导航栏组件 -->
|
||||||
<custom-navbar title="带图片背景的基础界面" />
|
<custom-navbar title="带图片背景的基础界面"
|
||||||
|
ref="customNavbar"/>
|
||||||
<view class="header" :style="{ backgroundColor: CommonEnum.BASE_COLOR }">
|
<view class="header" :style="{ backgroundColor: CommonEnum.BASE_COLOR }">
|
||||||
<!-- 状态展示 -->
|
<!-- 状态展示 -->
|
||||||
<status-display
|
<status-display
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user