方案一(所有tabbar页面都含下拉刷新):
tabbar页面:
<template>
<view class="tabBar">
<scroll-view class="tabBarContainer" @scrolltolower="scrollToLower" @refresherrefresh="refresherRefresh"
refresher-enabled :refresher-triggered="refresherTriggered" scroll-y>
<component :ref="key" :is="key" @stopPullDownRefresh="stopPullDownRefresh"></component>
</scroll-view>
<view class="tabBarFooter">
<template v-for="(item, index) in tabBarList">
<view class="item" :style="style({ item })" @click="change(item, index)">
<image class="icon" />
<text class="text">
{{ item.name }}
</text>
</view>
</template>
</view>
</view>
</template>
<script>
import home from "./home.vue";
import mine from "./mine.vue";
export default {
components: { home, mine },
data() {
return {
tabBarList: [
{
component: home,
name: "首页",
key: "home",
},
{
component: mine,
name: "我的",
key: "mine",
},
],
key: "home",
refresherTriggered: false,
};
},
onLoad(options) {
options.key ? this.key = options.key : "";
},
methods: {
style({ item }) {
return {
width: 100 / this.tabBarList.length + "%",
color: item.key == this.key ? "#298DF8" : "#333333",
};
},
change(item, index) {
this.key = item.key;
this.$nextTick(() => {
let page = this.$refs[item.key];
console.log(page)
page && page.init && page.init();
});
},
scrollToLower(e) {
console.log("页面触底", e);
let page = this.$refs[this.key];
page && page.scrollToLower && page.scrollToLower(e);
},
refresherRefresh(e) {
console.log("下拉刷新", e);
this.refresherTriggered = true;
let page = this.$refs[this.key];
page && page.refresherRefresh && page.refresherRefresh(e);
},
stopPullDownRefresh() {
this.refresherTriggered = false;
}
}
}
</script>
<style lang="scss" scoped>
$tabHeight: 75px;
$pageHeight: 100vh;
$isBackground: true;
// $pageHeight: 100vh;
// // #ifdef H5
// $pageHeight: calc(100vh - 44px);
// // #endif
.tabBar {
.tabBarContainer {
height: calc($pageHeight - $tabHeight);
@if $isBackground {
background: pink;
}
}
.tabBarFooter {
$iconSize: 16px;
height: $tabHeight;
box-shadow: 0px 4px 12px 0px rgba(0, 0, 0, 0.1);
display: flex;
.item {
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
height: 60px;
.icon {
width: 24px;
height: 24px;
@if $isBackground {
background: pink;
}
}
.text {
margin-top: 2px;
font-size: 14px;
}
}
}
}
</style>
home页面:
<template>
<view>
<view v-for="item in 100">{{ item }}</view>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
init(options = {}) {
console.log("home", options)
},
refresherRefresh(e) {
console.log("触发了下拉刷新");
setTimeout(() => {
this.$emit("stopPullDownRefresh");
}, 2000);
}
}
}
</script>
mine页面:
<template>
<view>mine</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
init(options = {}) {
console.log("mine", options)
},
refresherRefresh(e) {
console.log("触发了下拉刷新");
setTimeout(() => {
this.$emit("stopPullDownRefresh");
}, 2000);
}
}
}
</script>
方案二(页面单独做一个下拉刷新【推荐】):
tabbar页面:
<template>
<view class="tabBar">
<view class="tabBarContainer">
<component :ref="key" :is="key"></component>
</view>
<view class="tabBarFooter">
<template v-for="(item, index) in tabBarList">
<view class="item" :style="style({ item })" @click="change(item, index)">
<image class="icon" />
<text class="text">
{{ item.name }}
</text>
</view>
</template>
</view>
</view>
</template>
<script>
import home from "./home.vue";
import mine from "./mine.vue";
export default {
components: { home, mine },
data() {
return {
tabBarList: [
{
component: home,
name: "首页",
key: "home",
},
{
component: mine,
name: "我的",
key: "mine",
},
],
key: "home",
refresherTriggered: false,
};
},
onLoad(options) {
options.key ? this.key = options.key : "";
},
methods: {
style({ item }) {
return {
width: 100 / this.tabBarList.length + "%",
color: item.key == this.key ? "#298DF8" : "#333333",
};
},
change(item, index) {
this.key = item.key;
this.$nextTick(() => {
let page = this.$refs[item.key];
console.log(page)
page && page.init && page.init();
});
},
}
}
</script>
<style lang="scss" scoped>
$tabHeight: 75px;
$pageHeight: 100vh;
$isBackground: true;
// $pageHeight: 100vh;
// // #ifdef H5
// $pageHeight: calc(100vh - 44px);
// // #endif
.tabBar {
.tabBarContainer {
height: calc($pageHeight - $tabHeight);
overflow: hidden;
@if $isBackground {
background: pink;
}
}
.tabBarFooter {
$iconSize: 16px;
height: $tabHeight;
box-shadow: 0px 4px 12px 0px rgba(0, 0, 0, 0.1);
display: flex;
.item {
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
height: 60px;
.icon {
width: 24px;
height: 24px;
@if $isBackground {
background: pink;
}
}
.text {
margin-top: 2px;
font-size: 14px;
}
}
}
}
</style>
home页面:
<template>
<scroll-view class="home" @scrolltolower="scrollToLower" @refresherrefresh="refresherRefresh" refresher-enabled
:refresher-triggered="refresherTriggered" scroll-y>
<view>home</view>
<view v-for="item in 100">{{ item }}</view>
</scroll-view>
</template>
<script>
export default {
data() {
return {
refresherTriggered: false,
}
},
methods: {
init(options = {}) {
console.log("home", options)
},
scrollToLower(e) {
console.log("页面触底", e);
},
refresherRefresh(e) {
console.log("下拉刷新", e);
this.refresherTriggered = true;
setTimeout(() => {
this.stopPullDownRefresh();
}, 2000);
},
stopPullDownRefresh() {
this.refresherTriggered = false;
}
}
}
</script>
<style lang="scss" scoped>
.home {
height: calc(100%);
}
</style>
mine页面:
<template>
<view class="mine">
<view>mine</view>
<view v-for="item in 100">{{ item }}</view>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
init(options = {}) {
console.log("mine", options)
},
}
}
</script>
<style lang="scss" scoped>
.mine {
height: calc(100%);
overflow-y: scroll;
}
</style>
以上两种方案页面使用了scroll-view,可能会导致ios层级问题,需要注意。
VUE3版本自行修改。