Commit db0f2a3e authored by tao.huang's avatar tao.huang

feat: tabbar

parent bc0fc281
......@@ -7,51 +7,56 @@
:class="{ active: currentIndex === index }"
@click="handleTabClick(index, item)"
>
<image :src="currentIndex === index ? item.selectedIconPath : item.iconPath" class="tab-icon" />
<text class="tab-text" :class="{ active: currentIndex === index }">{{ item.text }}</text>
<image
:src="currentIndex === index ? item.selectedIconPath : item.iconPath"
:class="`tab-icon tab-icon-${index}`"
/>
<text class="tab-text" :class="{ active: currentIndex === index }">{{
item.text
}}</text>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue'
import { ref } from "vue";
const props = defineProps({
tabList: {
type: Array,
default: () => [
{
text: '首页',
iconPath: '/static/tabBar/icon_tab_home_normal.png',
selectedIconPath: '/static/tabBar/icon_tab_home_selected.png'
text: "首页",
iconPath: "/static/tabBar/icon_tab_home_normal.png",
selectedIconPath: "/static/tabBar/icon_tab_home_selected.png",
},
{
text: '品牌故事',
iconPath: '/static/tabBar/icon_tab_brand_normal.png',
selectedIconPath: '/static/tabBar/icon_tab_brand_selected.png'
text: "品牌故事",
iconPath: "/static/tabBar/icon_tab_brand_normal.png",
selectedIconPath: "/static/tabBar/icon_tab_brand_selected.png",
},
{
text: '积分服务',
iconPath: '/static/tabBar/icon_tab_gift_normal.png',
selectedIconPath: '/static/tabBar/icon_tab_gift_selected.png'
text: "积分服务",
iconPath: "/static/tabBar/icon_tab_gift_normal.png",
selectedIconPath: "/static/tabBar/icon_tab_gift_selected.png",
},
{
text: '我的',
iconPath: '/static/tabBar/icon_tab_person_normal.png',
selectedIconPath: '/static/tabBar/icon_tab_person_selected.png'
}
]
}
})
text: "我的",
iconPath: "/static/tabBar/icon_tab_person_normal.png",
selectedIconPath: "/static/tabBar/icon_tab_person_selected.png",
},
],
},
});
const emit = defineEmits(['tabClick'])
const emit = defineEmits(["tabClick"]);
const currentIndex = ref(0)
const currentIndex = ref(0);
const handleTabClick = (index, item) => {
currentIndex.value = index
emit('tabClick', { index, item })
}
currentIndex.value = index;
emit("tabClick", { index, item });
};
</script>
<style lang="scss" scoped>
......@@ -60,13 +65,13 @@ const handleTabClick = (index, item) => {
bottom: 0;
left: 0;
right: 0;
height: 100rpx;
height: 180rpx;
background-color: #ffffff;
display: flex;
justify-content: space-around;
align-items: center;
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
.tab-item {
flex: 1;
display: flex;
......@@ -74,21 +79,49 @@ const handleTabClick = (index, item) => {
align-items: center;
justify-content: center;
height: 100%;
.tab-icon {
width: 48rpx;
height: 48rpx;
margin-bottom: 4rpx;
position: absolute;
top: 28rpx;
}
.tab-icon-0 {
width: 36rpx;
height: 40rpx;
top: 28rpx;
}
.tab-icon-1 {
width: 34rpx;
height: 38rpx;
top: 29rpx;
}
.tab-icon-2 {
width: 38rpx;
height: 41rpx;
top: 24rpx;
}
.tab-icon-3 {
width: 36rpx;
height: 41rpx;
top: 28rpx;
}
.tab-text {
font-size: 24rpx;
font-size: 20rpx;
color: #666;
position: absolute;
top: 81rpx;
&.active {
color: #007AFF;
color: #b27c1e;
font-weight: 500;
}
}
}
}
</style>
\ No newline at end of file
</style>
<template>
<view class="container">
<Home v-if="curTabIndex == 0"></Home>
<Brand v-if="curTabIndex == 1"></Brand>
<Integral v-if="curTabIndex == 2"></Integral>
<My v-if="curTabIndex == 3"></My>
<component :is="tabComponents[curTabIndex]" />
<TabBar @tabClick="handleTabClick" />
</view>
</template>
......@@ -18,7 +15,8 @@
export default {
data() {
return {
curTabIndex: 0
curTabIndex: 0,
tabComponents: [Home, Brand, Integral, My]
};
},
onLoad() {},
......
{"version":3,"file":"TabBar.js","sources":["components/TabBar.vue","/Users/huangtao/Duiba/project/20250528_FHQ1/components/TabBar.vue?type=component"],"sourcesContent":["<template>\n <view class=\"tab-bar\">\n <view\n v-for=\"(item, index) in tabList\"\n :key=\"index\"\n class=\"tab-item\"\n :class=\"{ active: currentIndex === index }\"\n @click=\"handleTabClick(index, item)\"\n >\n <image :src=\"currentIndex === index ? item.selectedIconPath : item.iconPath\" class=\"tab-icon\" />\n <text class=\"tab-text\" :class=\"{ active: currentIndex === index }\">{{ item.text }}</text>\n </view>\n </view>\n</template>\n\n<script setup>\nimport { ref } from 'vue'\n\nconst props = defineProps({\n tabList: {\n type: Array,\n default: () => [\n {\n text: '首页',\n iconPath: '/static/tabBar/icon_tab_home_normal.png',\n selectedIconPath: '/static/tabBar/icon_tab_home_selected.png'\n },\n {\n text: '品牌故事',\n iconPath: '/static/tabBar/icon_tab_brand_normal.png',\n selectedIconPath: '/static/tabBar/icon_tab_brand_selected.png'\n },\n {\n text: '积分服务',\n iconPath: '/static/tabBar/icon_tab_gift_normal.png',\n selectedIconPath: '/static/tabBar/icon_tab_gift_selected.png'\n },\n {\n text: '我的',\n iconPath: '/static/tabBar/icon_tab_person_normal.png',\n selectedIconPath: '/static/tabBar/icon_tab_person_selected.png'\n }\n ]\n }\n})\n\nconst emit = defineEmits(['tabClick'])\n\nconst currentIndex = ref(0)\n\nconst handleTabClick = (index, item) => {\n currentIndex.value = index\n emit('tabClick', { index, item })\n}\n</script>\n\n<style lang=\"scss\" scoped>\n.tab-bar {\n position: fixed;\n bottom: 0;\n left: 0;\n right: 0;\n height: 100rpx;\n background-color: #ffffff;\n display: flex;\n justify-content: space-around;\n align-items: center;\n box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);\n \n .tab-item {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n \n .tab-icon {\n width: 48rpx;\n height: 48rpx;\n margin-bottom: 4rpx;\n }\n \n .tab-text {\n font-size: 24rpx;\n color: #666;\n \n &.active {\n color: #007AFF;\n }\n }\n }\n}\n</style> ","import Component from '/Users/huangtao/Duiba/project/20250528_FHQ1/components/TabBar.vue'\nwx.createComponent(Component)"],"names":["ref"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8CA,UAAM,OAAO;AAEb,UAAM,eAAeA,cAAG,IAAC,CAAC;AAE1B,UAAM,iBAAiB,CAAC,OAAO,SAAS;AACtC,mBAAa,QAAQ;AACrB,WAAK,YAAY,EAAE,OAAO,KAAI,CAAE;AAAA,IAClC;;;;;;;;;;;;;;;;;;ACpDA,GAAG,gBAAgB,SAAS;"}
\ No newline at end of file
{"version":3,"file":"TabBar.js","sources":["components/TabBar.vue","/Users/huangtao/Duiba/project/20250528_FHQ1/components/TabBar.vue?type=component"],"sourcesContent":["<template>\n <view class=\"tab-bar\">\n <view\n v-for=\"(item, index) in tabList\"\n :key=\"index\"\n class=\"tab-item\"\n :class=\"{ active: currentIndex === index }\"\n @click=\"handleTabClick(index, item)\"\n >\n <image\n :src=\"currentIndex === index ? item.selectedIconPath : item.iconPath\"\n :class=\"`tab-icon tab-icon-${index}`\"\n />\n <text class=\"tab-text\" :class=\"{ active: currentIndex === index }\">{{\n item.text\n }}</text>\n </view>\n </view>\n</template>\n\n<script setup>\nimport { ref } from \"vue\";\n\nconst props = defineProps({\n tabList: {\n type: Array,\n default: () => [\n {\n text: \"首页\",\n iconPath: \"/static/tabBar/icon_tab_home_normal.png\",\n selectedIconPath: \"/static/tabBar/icon_tab_home_selected.png\",\n },\n {\n text: \"品牌故事\",\n iconPath: \"/static/tabBar/icon_tab_brand_normal.png\",\n selectedIconPath: \"/static/tabBar/icon_tab_brand_selected.png\",\n },\n {\n text: \"积分服务\",\n iconPath: \"/static/tabBar/icon_tab_gift_normal.png\",\n selectedIconPath: \"/static/tabBar/icon_tab_gift_selected.png\",\n },\n {\n text: \"我的\",\n iconPath: \"/static/tabBar/icon_tab_person_normal.png\",\n selectedIconPath: \"/static/tabBar/icon_tab_person_selected.png\",\n },\n ],\n },\n});\n\nconst emit = defineEmits([\"tabClick\"]);\n\nconst currentIndex = ref(0);\n\nconst handleTabClick = (index, item) => {\n currentIndex.value = index;\n emit(\"tabClick\", { index, item });\n};\n</script>\n\n<style lang=\"scss\" scoped>\n.tab-bar {\n position: fixed;\n bottom: 0;\n left: 0;\n right: 0;\n height: 180rpx;\n background-color: #ffffff;\n display: flex;\n justify-content: space-around;\n align-items: center;\n box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);\n\n .tab-item {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n\n .tab-icon {\n width: 48rpx;\n height: 48rpx;\n\n position: absolute;\n top: 28rpx;\n }\n\n .tab-icon-0 {\n width: 36rpx;\n height: 40rpx;\n top: 28rpx;\n }\n .tab-icon-1 {\n width: 34rpx;\n height: 38rpx;\n top: 29rpx;\n }\n .tab-icon-2 {\n width: 38rpx;\n height: 41rpx;\n top: 24rpx;\n }\n\n .tab-icon-3 {\n width: 36rpx;\n height: 41rpx;\n top: 28rpx;\n }\n\n .tab-text {\n font-size: 20rpx;\n color: #666;\n\n position: absolute;\n top: 81rpx;\n\n &.active {\n color: #b27c1e;\n font-weight: 500;\n }\n }\n }\n}\n</style>\n","import Component from '/Users/huangtao/Duiba/project/20250528_FHQ1/components/TabBar.vue'\nwx.createComponent(Component)"],"names":["ref"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmDA,UAAM,OAAO;AAEb,UAAM,eAAeA,cAAAA,IAAI,CAAC;AAE1B,UAAM,iBAAiB,CAAC,OAAO,SAAS;AACtC,mBAAa,QAAQ;AACrB,WAAK,YAAY,EAAE,OAAO,KAAM,CAAA;AAAA,IAClC;;;;;;;;;;;;;;;;;;;ACzDA,GAAG,gBAAgB,SAAS;"}
\ No newline at end of file
......@@ -85,9 +85,29 @@ const def = (obj, key, value) => {
});
};
const looseToNumber = (val) => {
const n = parseFloat(val);
return isNaN(n) ? val : n;
const n2 = parseFloat(val);
return isNaN(n2) ? val : n2;
};
function normalizeClass(value) {
let res = "";
if (isString(value)) {
res = value;
} else if (isArray(value)) {
for (let i = 0; i < value.length; i++) {
const normalized = normalizeClass(value[i]);
if (normalized) {
res += normalized + " ";
}
}
} else if (isObject(value)) {
for (const name in value) {
if (value[name]) {
res += name + " ";
}
}
}
return res.trim();
}
const toDisplayString = (val) => {
return isString(val) ? val : val == null ? "" : isArray(val) || isObject(val) && (val.toString === objectToString || !isFunction(val.toString)) ? JSON.stringify(val, replacer, 2) : String(val);
};
......@@ -5132,6 +5152,7 @@ function vFor(source, renderItem) {
const o = (value, key) => vOn(value, key);
const f = (source, renderItem) => vFor(source, renderItem);
const e = (target, ...sources) => extend(target, ...sources);
const n = (value) => normalizeClass(value);
const t = (val) => toDisplayString(val);
function createApp$1(rootComponent, rootProps = null) {
rootComponent && (rootComponent.mpType = "app");
......@@ -5723,8 +5744,8 @@ const $once = defineSyncApi(API_ONCE, (name, callback) => {
const $off = defineSyncApi(API_OFF, (name, callback) => {
if (!isArray(name))
name = name ? [name] : [];
name.forEach((n) => {
eventBus.off(n, callback);
name.forEach((n2) => {
eventBus.off(n2, callback);
});
}, OffProtocol);
const $emit = defineSyncApi(API_EMIT, (name, ...args) => {
......@@ -7905,6 +7926,7 @@ exports.createSSRApp = createSSRApp;
exports.e = e;
exports.f = f;
exports.index = index;
exports.n = n;
exports.o = o;
exports.ref = ref;
exports.resolveComponent = resolveComponent;
......
......@@ -42,11 +42,12 @@ const _sfc_main = {
a: common_vendor.f(__props.tabList, (item, index, i0) => {
return {
a: currentIndex.value === index ? item.selectedIconPath : item.iconPath,
b: common_vendor.t(item.text),
c: currentIndex.value === index ? 1 : "",
d: index,
e: currentIndex.value === index ? 1 : "",
f: common_vendor.o(($event) => handleTabClick(index, item), index)
b: common_vendor.n(`tab-icon tab-icon-${index}`),
c: common_vendor.t(item.text),
d: currentIndex.value === index ? 1 : "",
e: index,
f: currentIndex.value === index ? 1 : "",
g: common_vendor.o(($event) => handleTabClick(index, item), index)
};
})
};
......
<view class="tab-bar data-v-89ca1f91"><view wx:for="{{a}}" wx:for-item="item" wx:key="d" class="{{['tab-item', 'data-v-89ca1f91', item.e && 'active']}}" bindtap="{{item.f}}"><image src="{{item.a}}" class="tab-icon data-v-89ca1f91"/><text class="{{['tab-text', 'data-v-89ca1f91', item.c && 'active']}}">{{item.b}}</text></view></view>
\ No newline at end of file
<view class="tab-bar data-v-89ca1f91"><view wx:for="{{a}}" wx:for-item="item" wx:key="e" class="{{['tab-item', 'data-v-89ca1f91', item.f && 'active']}}" bindtap="{{item.g}}"><image src="{{item.a}}" class="{{['data-v-89ca1f91', item.b]}}"/><text class="{{['tab-text', 'data-v-89ca1f91', item.d && 'active']}}">{{item.c}}</text></view></view>
\ No newline at end of file
......@@ -28,7 +28,7 @@
bottom: 0;
left: 0;
right: 0;
height: 100rpx;
height: 180rpx;
background-color: #ffffff;
display: flex;
justify-content: space-around;
......@@ -46,12 +46,36 @@
.tab-bar .tab-item .tab-icon.data-v-89ca1f91 {
width: 48rpx;
height: 48rpx;
margin-bottom: 4rpx;
position: absolute;
top: 28rpx;
}
.tab-bar .tab-item .tab-icon-0.data-v-89ca1f91 {
width: 36rpx;
height: 40rpx;
top: 28rpx;
}
.tab-bar .tab-item .tab-icon-1.data-v-89ca1f91 {
width: 34rpx;
height: 38rpx;
top: 29rpx;
}
.tab-bar .tab-item .tab-icon-2.data-v-89ca1f91 {
width: 38rpx;
height: 41rpx;
top: 24rpx;
}
.tab-bar .tab-item .tab-icon-3.data-v-89ca1f91 {
width: 36rpx;
height: 41rpx;
top: 28rpx;
}
.tab-bar .tab-item .tab-text.data-v-89ca1f91 {
font-size: 24rpx;
font-size: 20rpx;
color: #666;
position: absolute;
top: 81rpx;
}
.tab-bar .tab-item .tab-text.active.data-v-89ca1f91 {
color: #007AFF;
color: #b27c1e;
font-weight: 500;
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment