taro react hooks 小程序自定义头部,第一次写,自己记录
- title: 标题
- isOccupySpace: 是否占位
- leftSolt: 左侧solt
- centerSolt: 中间solt
- background: 背景色
- isShowHome: 是否需要回到首页按钮
- isShowSearch: 是否需要左侧搜索
- backColor: 返回按钮颜色(黑色false,白色true, 默认false黑色)
- logoTextWhite: 白色logo
- logoTextBlack: 黑色logo
- logoPosition: logo位置(左侧-left,中间-center)
- getCustomBarHeight: 获取导航高度:function
import React, { ReactNode, useEffect, memo } from 'react';
import { View, Image } from '@tarojs/components';
import { getCurrentPages, getSystemInfoSync, getMenuButtonBoundingClientRect } from '@tarojs/taro';
const { statusBarHeight, windowWidth } = getSystemInfoSync();
const customInfo = getMenuButtonBoundingClientRect();
// 导航高度
const custonBarHeight = (customInfo.top - statusBarHeight) * 2 + customInfo.height + statusBarHeight;
// 左侧区域宽度
const leftWidth = windowWidth - customInfo.left;
// 中心区域宽度
const centerWidth = windowWidth - (windowWidth - customInfo.left) * 2;
const padLeft = windowWidth - customInfo.left - customInfo.width;
interface RenderProps {
title?: string;
leftSolt?: ReactNode;
centerSolt?: ReactNode;
background?: string;
isOccupySpace?: boolean;
isShowHome?: boolean;
isShowSearch?: boolean;
backColor?: boolean;
logoTextWhite?: boolean;
logoTextBlack?: boolean;
logoPosition?: 'left' | 'center';
textColor?: string;
getCustomBarHeight?: (custonBarHeight: number) => void;
}
const NavBar: React.FC<RenderProps> = ({
isOccupySpace = true,
leftSolt,
centerSolt,
title = '',
background = '#fff',
isShowHome = false,
isShowSearch = false,
backColor = false,
logoTextWhite = false,
logoTextBlack = false,
logoPosition = 'center',
textColor = '',
getCustomBarHeight,
}) => {
const pagesLength = getCurrentPages().length;
const leftArrow = pagesLength > 1;
useEffect(() => {
if (typeof getCustomBarHeight === 'function') getCustomBarHeight(custonBarHeight);
}, []);
return (
<>
<View
className={`${styles['nav-bar']} ${styles['nav-bar__fix']}`}
style={{ paddingTop: `${statusBarHeight}PX`, height: `${custonBarHeight}PX`, background: `${background}` }}
>
// 左侧
<View className={styles['nav-bar-left']} style={{ width: `${leftWidth}PX`, paddingLeft: `${isShowHome && leftArrow ? padLeft + 'PX' : '32rpx'}` }}>
{leftSolt ||
(logoTextBlack && logoPosition == 'left' && <LogoTextBarBlack logoPosition={logoPosition} />) ||
(logoTextWhite && logoPosition == 'left' && <LogoTextBarWhite />) ||
(isShowSearch && <SearchBar />) ||
(leftArrow && <LeftArrowBack isShowHome={isShowHome} backColor={backColor} />) || <HomeBar leftArrow={leftArrow} LeftArrowBack={LeftArrowBack} />}
</View>
// 中间
<View className={`${styles['nav-bar-center']} ${textColor === 'white' && styles['white']}`} style={{ width: `${centerWidth}PX` }}>
{centerSolt ||
(logoTextBlack && logoPosition == 'center' && <LogoTextBarBlack logoPosition={logoPosition} />) ||
(logoTextWhite && logoPosition == 'center' && <LogoTextBarWhite />) ||
title}
</View>
// 右侧占位
<View className={styles['nav-bar-right']} style={{ width: `${leftWidth}PX` }}></View>
</View>
// 导航占位
{isOccupySpace && <View style={{ height: `${custonBarHeight}PX` }}></View>}
</>
);
};
export default memo(NavBar);
const LeftArrowBack = ({ isShowHome, backColor }) => {
return (
<>
{isShowHome ? (
<View className={styles['nav-bar-left__btn']} style={{ height: `${customInfo.height}PX` }}>
<View className={styles['back_icon']} onClick={() => navigateBack()}>
<Image mode="widthFix" src={IMG_URL + 'left.svg'} />
</View>
<View className={styles['back_line']}></View>
<View className={styles['back_home']} onClick={() => reLaunch('/pages/index/index')}>
<Image mode="widthFix" src={IMG_URL + 'home.svg'} />
</View>
</View>
) : (
<View className={styles['nav-bar-left__btn__back']} style={{ height: `${customInfo.height}PX` }}>
<View className={styles['back_icon']} onClick={() => navigateBack()}>
<Image className={styles['back_icon-img']} mode="widthFix" src={IMG_URL + `${backColor ? 'left_white.svg' : 'left.svg'}`} />
</View>
</View>
)}
</>
);
};
const HomeBar = ({ leftArrow, LeftArrowBack }) => {
return (
<>
{leftArrow ? (
<LeftArrowBack />
) : (
<View className={styles['nav-bar-left__btn__search']} onClick={() => reLaunch('/pages/index/index')}>
<View className={styles['search_icon']}>
<Image mode="widthFix" src={IMG_URL + 'home.svg'} />
</View>
</View>
)}
</>
);
};
const SearchBar = () => {
return (
<View className={styles['nav-bar-left__btn__search']} onClick={() =>{}}>
<View className={styles['search_icon']}>
<Image mode="widthFix" src='search.svg'} />
</View>
</View>
);
};
const LogoTextBarWhite = () => {
return (
<View className={styles['nav-logo']}>
<View className={styles['logo_icon']} onClick={() =>{}}>
<Image mode="widthFix" src='logo-white.svg' />
</View>
</View>
);
};
const LogoTextBarBlack = ({ logoPosition }) => {
return (
<View className={styles['nav-logo']} onClick={() =>{}}>
<View className={`${styles['logo_icon']} ${logoPosition === 'left' && styles['logo-left']}}`}>
<Image mode="widthFix" src="" />
</View>
</View>
);
};
css
.nav-bar {
display: flex;
align-items: center;
flex-shrink: 0;
&.nav-bar__fix {
position: fixed;
width: 100vw;
left: 0;
top: 0;
z-index: 9;
}
&-left {
width: 25%;
display: flex;
align-items: center;
&__btn {
width: 174rpx;
height: 64rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 64rpx;
border: 1PX solid rgba(151, 151, 151, 0.201002);
.back_icon{
width: 40rpx;
height: 40rpx;
}
.back_line{
background: rgba(0, 0, 0, 0.198907);
width: 1PX;
height: 36rpx;
margin: 0 18rpx;
}
.back_home{
width: 40rpx;
height: 40rpx;
}
}
.nav-bar-left__btn__search{
background: rgba(255, 255, 255, 0.3);
border: 1PX solid rgba(151, 151, 151, 0.201002);
width: 64rpx;
height: 64rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
.search_icon{
width: 36rpx;
}
}
.nav-bar-left__btn__back{
width: 64rpx;
height: 64rpx;
border-radius: 64rpx;
border: 1PX solid rgba(151, 151, 151, 0.201002);
display: flex;
align-items: center;
justify-content: center;
.back_icon{
width: 40rpx;
height: 40rpx;
.back_icon-img{
margin-left: -2rpx;
}
}
}
}
&-left-home {
width: 122rpx;;
display: flex;
align-items: center;
&__btn {
width: 84rpx;
display: flex;
align-items: center;
justify-content: center;
}
}
.nav-logo{
.logo_icon{
width: 172rpx;
}
.logo-left {
width: 142rpx;
}
}
&-center {
width: 50%;
text-align: center;
color: #000;
font-weight: 500;
font-size: 36rpx;
display: flex;
align-items: center;
justify-content: center;
&.white {
color: #fff;
}
}
&-center-home {
flex:1;
text-align: center;
color: #fff;
font-weight: 500;
font-size: 32rpx;
}
&-right {
width: 25%;
}
}