Skip to content

Commit

Permalink
feat: 新增 NavigationBar 组件
Browse files Browse the repository at this point in the history
  • Loading branch information
fjc0k committed Aug 22, 2019
1 parent 2c2b12a commit 33341bd
Show file tree
Hide file tree
Showing 21 changed files with 306 additions and 67 deletions.
2 changes: 1 addition & 1 deletion src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ class App extends Taro.Component {
],
window: {
navigationBarTitleText: 'Mounted',
navigationBarBackgroundColor: '#1AAD19',
navigationBarTextStyle: 'white',
backgroundColor: '#E8E8E8',
navigationStyle: 'custom',
},
}

Expand Down
84 changes: 84 additions & 0 deletions src/components/NavigationBar/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
@import '../../styles/settings.scss';

.m-navigation-bar {
&__container {
position: fixed;
top: 0;
left: 0;
right: 0;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
z-index: 8000;
}

&__left {
position: absolute;
left: 0;
}

&__menu {
display: flex;
align-items: center;
justify-content: space-around;
font-weight: bold;
font-size: 18px;
border: 1px solid;

&-left, &-right {
flex-grow: 1;
text-align: center;
}

&-divider {
flex-shrink: 0;
width: 1px;
height: 1em;
}
}

&__title {
font-weight: bold;
font-size: 18px;
}

&_white &__menu {
background: rgba(black, 0.15);
border-color: rgba(white, 0.25);
}

&_white &__menu-divider {
background: rgba(white, 0.25);
}

&_black &__menu {
background: rgba(white, 0.55);
border-color: rgba(black, 0.25);
}

&_black &__menu-divider {
background: rgba(black, 0.15);
}
}

@font-face {
font-family: "m-navigation-bar-iconfont";
src: url("data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAUQAAsAAAAACCAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADMAAABCsP6z7U9TLzIAAAE8AAAARAAAAFY8d0gqY21hcAAAAYAAAABVAAABhmUs0M9nbHlmAAAB2AAAAR8AAAE8ILsQx2hlYWQAAAL4AAAAMQAAADYWIqFMaGhlYQAAAywAAAAgAAAAJAfbA4RobXR4AAADTAAAAAwAAAAMDAD//WxvY2EAAANYAAAACAAAAAgAJACebWF4cAAAA2AAAAAeAAAAIAEPAFpuYW1lAAADgAAAAWsAAAM5gIrW4nBvc3QAAATsAAAAJAAAADXT7s3PeJxjYGRgYOBikGPQYWB0cfMJYeBgYGGAAJAMY05meiJQDMoDyrGAaQ4gZoOIAgCKIwNPAHicY2BkYWCcwMDKwMHUyXSGgYGhH0IzvmYwYuRgYGBiYGVmwAoC0lxTGByeMT6zYG7438AQw9zA0AAUZgTJAQDhYgwceJztkMERgCAMBPdAeTgW4sMCKMWX5dMGHkG78GY2l1zgE2AFsjnNAroRQ5dTRZ7ZIl/iTbGL1NRq7/C5Je+KPY1/Kvzaox7vlMa1JtHXCXoADR8OKgAAAHicHY6/SsNAAMbvyyV3pAXhriGxpLGSkwRKifTfhSJI6eIkdPAV6ugoOhgh3RwdnbvVF/ABXARfwDdx6MWzyw8++H4fHwEhzRvl9JYIQrw0RzYtocdhwH2EAXO+j4W5EQLv4lwJU6EWai2wk4XETqhCmspUslDEafZNTff0meTkmhAfBVLGcYToBNFEHJDpC4xDLiaXKA/QGVciYBY6y5Xt2kXkQqWZKvX/jQhh3+7QH/Mki2nRMVXiMZqkcyzLLXi37nJsyyXmaUIZWz724zUGs3o2wDru4wGAR11s5Fhi41LP5k+8doKgY+5OR+1WAvOlVw6u4l4vNh/OSkMjabVHZ+YlHgJcL4CFNr8Yxrh3feZZ27oe811C/gAnVjyHAHicY2BkYGAA4grD63vj+W2+MnCzMIDAzWa95TD6/9//TSwMzPVALgcDE0gUAFMKDF0AAAB4nGNgZGBgbvjfwBDDwvD/LwMDCwMDUAQFMAMAdawEaAQAAAAEAAAABAD//QAAAAAAJACeeJxjYGRgYGBm8GNgYgABEMkFhAwM/8F8BgAQZwFqAAB4nJ2SPU7DQBCFn/OHSCQKEEh020ABsvOD0qSNlHQUKdI7ztpxZHujzSZSzsABOAUtd+AScAguwJMzaUApglceffvezOyPFsAlPuFh/13z37OHW872XMEZAuEq9b5wjfwsXEcLiXCDuhVu4hEvwi1c4Z0dvNo5Zw/4EPbQw7dwBRfenXAVPe9JuEbWwnXceK/CDepvwk1MvS/hFu4r/ebQ6tDpuZrtVBqZIjaFa+Z+EW7TJHSpKfxZaP2DM9HJJgvtUf+oMdV2TU11g87RnLEutD3sZb1Nes7FKrYmVyO6OsuMWlmz1JELFs6tBu12LHoQmZxHG/JKNUI4xjkUZtgxpohgUCAuo2NeDp8UYksvKfPT0vNZEbKH/6dmwo4JNshK//T60yumXNFiLXkKXT6vzj/6jNmnKHv9vpc1uyR8Vo4j5jxmjuEKCiOp1TxvRlZYld6SSkQ9wKKsWmGANkf8Kz8o95D/AJjlo1sAeJxjYGKAAC4G7ICZkYmRmZGFgSUpMTmbJSM/N5WBAQAZ7QNe") format("woff");
}

.m-navigation-bar-iconfont {
font-family: "m-navigation-bar-iconfont" !important;
font-size: 1em;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

.m-navigation-bar-icon-home:before {
content: "\e601";
}

.m-navigation-bar-icon-back:before {
content: "\e638";
}
128 changes: 128 additions & 0 deletions src/components/NavigationBar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import './index.scss'
import Taro from '@tarojs/taro'
import { component } from '../component'
import { internalStore } from '../internal'
import { last } from 'vtils'
import { NavigationBarProps } from './props'
import { View } from '@tarojs/components'

function onlyPath(url: string) {
return url ? url.split('?')[0].replace(/^\/+/, '') : ''
}

export default class NavigationBar extends component({
props: NavigationBarProps,
state: {
verticalPadding: 0 as number,
horizontalPadding: 0 as number,
navigationBarHeight: 0 as number,
navigationBarFullHeight: 0 as number,
menuButtonHeight: 0 as number,
menuButtonWidth: 0 as number,
backButtonVisible: false as boolean,
homeButtonVisible: false as boolean,
},
}) {
componentDidShow() {
const menuRect = Taro.getMenuButtonBoundingClientRect()
const sysInfo = Taro.getSystemInfoSync()
const verticalPadding = menuRect.top - sysInfo.statusBarHeight
const horizontalPadding = sysInfo.windowWidth - menuRect.right
const height = menuRect.height + verticalPadding * 2
const fullHeight = sysInfo.statusBarHeight + height

const pages = Taro.getCurrentPages()
const backButtonVisible = pages.length > 1
const homeButtonVisible = onlyPath(last(pages).route) !== onlyPath(this.props.homePath)

internalStore.customNavigationBarFullHeight = fullHeight

this.setState({
verticalPadding: verticalPadding,
horizontalPadding: horizontalPadding,
navigationBarHeight: height,
navigationBarFullHeight: fullHeight,
menuButtonHeight: menuRect.height,
menuButtonWidth: menuRect.width,
backButtonVisible: backButtonVisible,
homeButtonVisible: homeButtonVisible,
})
}

componentDidHide() {
internalStore.customNavigationBarFullHeight = 0
}

componentWillUnmount() {
internalStore.customNavigationBarFullHeight = 0
}

handleBackClick = () => {
Taro.navigateBack()
}

handleHomeClick = () => {
Taro.navigateTo({
url: this.props.homePath,
})
}

render() {
const { backgroundColor, textStyle, className } = this.props
const { verticalPadding, horizontalPadding, navigationBarHeight, navigationBarFullHeight, menuButtonHeight, menuButtonWidth, backButtonVisible, homeButtonVisible } = this.state

const actualBackgroundColor = backgroundColor !== 'auto'
? backgroundColor
: textStyle === 'white'
? '#000000'
: '#FFFFFF'

return (
<View className={`m-navigation-bar m-navigation-bar_${textStyle} ${className}`}>
<View
className='m-navigation-bar__placeholder'
style={{ height: `${navigationBarFullHeight}px` }}
/>
<View
className='m-navigation-bar__container'
style={{
backgroundColor: actualBackgroundColor,
color: textStyle,
height: `${navigationBarFullHeight}px`,
padding: `${navigationBarFullHeight - navigationBarHeight + verticalPadding}px ${horizontalPadding}px ${verticalPadding}px ${horizontalPadding}px`,
}}>
{!backButtonVisible && !homeButtonVisible ? null : (
<View className='m-navigation-bar__left' style={{ left: `${verticalPadding}px` }}>
<View
className='m-navigation-bar__menu'
style={{
width: `${backButtonVisible && homeButtonVisible ? menuButtonWidth : menuButtonWidth / 2}px`,
height: `${menuButtonHeight}px`,
borderRadius: `${menuButtonHeight / 2}px`,
}}>
{!backButtonVisible ? null : (
<View
className='m-navigation-bar__menu-left m-navigation-bar-iconfont m-navigation-bar-icon-back'
onClick={this.handleBackClick}
/>
)}
{!(backButtonVisible && homeButtonVisible) ? null : (
<View className='m-navigation-bar__menu-divider' />
)}
{!homeButtonVisible ? null : (
<View
className='m-navigation-bar__menu-right m-navigation-bar-iconfont m-navigation-bar-icon-home'
onClick={this.handleHomeClick}
/>
)}
</View>
</View>
)}
<View className='m-navigation-bar__title'>
{this.props.children}
</View>
</View>
</View>
)
}
}
26 changes: 26 additions & 0 deletions src/components/NavigationBar/props.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { RequiredProp } from '../component'

export const NavigationBarProps = {
/**
* 小程序主页的绝对路径,可带参数。
*
* @example '/pages/index/index?id=40'
*/
homePath: '' as any as RequiredProp<string>,

/**
* 导航栏字体颜色,务必同时设置 `app.json` 中的 `window.navigationBarTextStyle` 且保持二者一致。
*
* @default 'white'
*/
textStyle: 'white' as 'white' | 'black',

/**
* 导航栏背景颜色。默认值是 `auto`,表示:
* - 若 `textStyle='white'`,则 `backgroundColor='#000000'`;
* - 若 `textStyle='black'`,则 `backgroundColor='#FFFFFF'`。
*
* @default 'auto'
*/
backgroundColor: 'auto' as string,
}
7 changes: 4 additions & 3 deletions src/components/Popup/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import MTransition from '../Transition'
import store from '../store'
import Taro from '@tarojs/taro'
import { CommonEventFunction } from '@tarojs/components/types/common'
import { component } from '../component'
import { internalStore } from '../internal'
import { MPopupProps, Position, TransitionName } from './props'
import { View } from '@tarojs/components'

Expand Down Expand Up @@ -31,7 +31,7 @@ export default class MPopup extends component({

componentWillMount() {
this.setState({
zIndex: store.zIndex++,
zIndex: internalStore.zIndex++,
display: this.props.visible,
})
}
Expand Down Expand Up @@ -90,7 +90,8 @@ export default class MPopup extends component({
<View
className={`m-popup m-popup_${position} ${className}`}
style={{
zIndex,
zIndex: zIndex,
top: `${internalStore.customNavigationBarFullHeight}px`,
...(display ? {} : { display: 'none' }),
}}
onTouchMove={this.handleTouchMove}>
Expand Down
7 changes: 5 additions & 2 deletions src/components/Sticky/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Taro from '@tarojs/taro'
import { component } from '../component'
import { Disposer, wait } from 'vtils'
import { internalStore } from '../internal'
import { MStickyProps } from './props'
import { View } from '@tarojs/components'

Expand Down Expand Up @@ -57,7 +58,7 @@ export default class MSticky extends component({
})

// 监听吸顶内容的位置
const top = -(this.index === 0 ? 0 : height)
const top = -(this.index === 0 ? internalStore.customNavigationBarFullHeight : height)
const intersectionObserver = wx.createIntersectionObserver(this.$scope)
const relativeToViewport = intersectionObserver.relativeToViewport({ top }) as any
relativeToViewport.observe(
Expand Down Expand Up @@ -100,7 +101,9 @@ export default class MSticky extends component({
<View
className={`m-sticky ${fixed && 'm-sticky_fixed'} ${className}`}
style={contentHeight ? { height: `${contentHeight}px` } : {}}>
<View className='m-sticky__content'>
<View
className='m-sticky__content'
style={{ top: `${internalStore.customNavigationBarFullHeight}px` }}>
{this.props.children}
</View>
</View>
Expand Down
2 changes: 2 additions & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// @index('./[A-Z]*', (pp, cc) => `export { default as M${pp.name} } from '${pp.path}'`)
export { default as MDatePicker } from './DatePicker'
export { default as MECharts } from './ECharts'
export { default as MNavigationBar } from './NavigationBar'
export { default as MPicker } from './Picker'
export { default as MPickerView } from './PickerView'
export { default as MPopup } from './Popup'
Expand All @@ -14,6 +15,7 @@ export type ComponentName = (
// @index('./[A-Z]*', (pp, cc, { last }) => `'${pp.name}'${last ? '' : ' |'}`)
'DatePicker' |
'ECharts' |
'NavigationBar' |
'Picker' |
'PickerView' |
'Popup' |
Expand Down
4 changes: 4 additions & 0 deletions src/components/internal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const internalStore = {
zIndex: 5000,
customNavigationBarFullHeight: 0,
}
5 changes: 0 additions & 5 deletions src/components/store.ts

This file was deleted.

9 changes: 3 additions & 6 deletions src/pages/DatePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import Taro, { Config, ShareAppMessageReturn } from '@tarojs/taro'
import Taro, { ShareAppMessageReturn } from '@tarojs/taro'
import { component } from '../components/component'
import { Image, View } from '@tarojs/components'
import { MDatePicker } from '../components'
import { pageUrls } from '.'
import { XBackHome, XItem, XList, XTitle } from './components'
import { XBackHome, XItem, XList, XNavigationBar, XTitle } from './components'

const codeImg = 'https://ae01.alicdn.com/kf/Ua09c76aa494640e89c84432e7ad02a381.png'

Expand All @@ -12,10 +12,6 @@ export default class DatePicker extends component({
selectedDate: [2013, 5, 20],
},
}) {
config: Config = {
navigationBarTitleText: 'DatePicker',
}

onShareAppMessage(): ShareAppMessageReturn {
return {
title: 'DatePicker',
Expand All @@ -27,6 +23,7 @@ export default class DatePicker extends component({
const { selectedDate } = this.state
return (
<View>
<XNavigationBar>DatePicker</XNavigationBar>
<XTitle>日期选择</XTitle>
<XList>
<MDatePicker
Expand Down
9 changes: 3 additions & 6 deletions src/pages/ECharts.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import './ECharts.scss'
import Taro, { Config, ShareAppMessageReturn } from '@tarojs/taro'
import Taro, { ShareAppMessageReturn } from '@tarojs/taro'
import { component } from '../components/component'
import { MECharts } from '../components'
import { pageUrls } from '.'
import { View } from '@tarojs/components'
import { XBackHome, XItem, XList, XTitle } from './components'
import { XBackHome, XItem, XList, XNavigationBar, XTitle } from './components'

const getECharts = () => require('echarts/dist/echarts.min.js')

Expand All @@ -14,10 +14,6 @@ export default class ECharts extends component({
selectedCountryIndex: 0,
},
}) {
config: Config = {
navigationBarTitleText: 'ECharts',
}

onShareAppMessage(): ShareAppMessageReturn {
return {
title: 'ECharts',
Expand All @@ -28,6 +24,7 @@ export default class ECharts extends component({
render() {
return (
<View>
<XNavigationBar>ECharts</XNavigationBar>
<XTitle>雷达图</XTitle>
<XList>
<XItem>
Expand Down
Loading

0 comments on commit 33341bd

Please sign in to comment.