diff --git a/src/app.tsx b/src/app.tsx
index be24a70..22fde88 100644
--- a/src/app.tsx
+++ b/src/app.tsx
@@ -20,9 +20,9 @@ class App extends Taro.Component {
],
window: {
navigationBarTitleText: 'Mounted',
- navigationBarBackgroundColor: '#1AAD19',
navigationBarTextStyle: 'white',
backgroundColor: '#E8E8E8',
+ navigationStyle: 'custom',
},
}
diff --git a/src/components/NavigationBar/index.scss b/src/components/NavigationBar/index.scss
new file mode 100644
index 0000000..6f3b5f3
--- /dev/null
+++ b/src/components/NavigationBar/index.scss
@@ -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";
+}
diff --git a/src/components/NavigationBar/index.tsx b/src/components/NavigationBar/index.tsx
new file mode 100644
index 0000000..3ba8e7c
--- /dev/null
+++ b/src/components/NavigationBar/index.tsx
@@ -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 (
+
+
+
+ {!backButtonVisible && !homeButtonVisible ? null : (
+
+
+ {!backButtonVisible ? null : (
+
+ )}
+ {!(backButtonVisible && homeButtonVisible) ? null : (
+
+ )}
+ {!homeButtonVisible ? null : (
+
+ )}
+
+
+ )}
+
+ {this.props.children}
+
+
+
+ )
+ }
+}
diff --git a/src/components/NavigationBar/props.ts b/src/components/NavigationBar/props.ts
new file mode 100644
index 0000000..2d8c874
--- /dev/null
+++ b/src/components/NavigationBar/props.ts
@@ -0,0 +1,26 @@
+import { RequiredProp } from '../component'
+
+export const NavigationBarProps = {
+ /**
+ * 小程序主页的绝对路径,可带参数。
+ *
+ * @example '/pages/index/index?id=40'
+ */
+ homePath: '' as any as RequiredProp,
+
+ /**
+ * 导航栏字体颜色,务必同时设置 `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,
+}
diff --git a/src/components/Popup/index.tsx b/src/components/Popup/index.tsx
index 92ebe74..1131fd7 100644
--- a/src/components/Popup/index.tsx
+++ b/src/components/Popup/index.tsx
@@ -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'
@@ -31,7 +31,7 @@ export default class MPopup extends component({
componentWillMount() {
this.setState({
- zIndex: store.zIndex++,
+ zIndex: internalStore.zIndex++,
display: this.props.visible,
})
}
@@ -90,7 +90,8 @@ export default class MPopup extends component({
diff --git a/src/components/Sticky/index.tsx b/src/components/Sticky/index.tsx
index 69d1625..1e52f38 100644
--- a/src/components/Sticky/index.tsx
+++ b/src/components/Sticky/index.tsx
@@ -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'
@@ -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(
@@ -100,7 +101,9 @@ export default class MSticky extends component({
-
+
{this.props.children}
diff --git a/src/components/index.ts b/src/components/index.ts
index c245b79..1964430 100644
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -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'
@@ -14,6 +15,7 @@ export type ComponentName = (
// @index('./[A-Z]*', (pp, cc, { last }) => `'${pp.name}'${last ? '' : ' |'}`)
'DatePicker' |
'ECharts' |
+ 'NavigationBar' |
'Picker' |
'PickerView' |
'Popup' |
diff --git a/src/components/internal.ts b/src/components/internal.ts
new file mode 100644
index 0000000..e324e4b
--- /dev/null
+++ b/src/components/internal.ts
@@ -0,0 +1,4 @@
+export const internalStore = {
+ zIndex: 5000,
+ customNavigationBarFullHeight: 0,
+}
diff --git a/src/components/store.ts b/src/components/store.ts
deleted file mode 100644
index 1589023..0000000
--- a/src/components/store.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-const store = {
- zIndex: 5000,
-}
-
-export default store
diff --git a/src/pages/DatePicker.tsx b/src/pages/DatePicker.tsx
index 68cdb99..cd175c6 100644
--- a/src/pages/DatePicker.tsx
+++ b/src/pages/DatePicker.tsx
@@ -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'
@@ -12,10 +12,6 @@ export default class DatePicker extends component({
selectedDate: [2013, 5, 20],
},
}) {
- config: Config = {
- navigationBarTitleText: 'DatePicker',
- }
-
onShareAppMessage(): ShareAppMessageReturn {
return {
title: 'DatePicker',
@@ -27,6 +23,7 @@ export default class DatePicker extends component({
const { selectedDate } = this.state
return (
+ DatePicker
日期选择
require('echarts/dist/echarts.min.js')
@@ -14,10 +14,6 @@ export default class ECharts extends component({
selectedCountryIndex: 0,
},
}) {
- config: Config = {
- navigationBarTitleText: 'ECharts',
- }
-
onShareAppMessage(): ShareAppMessageReturn {
return {
title: 'ECharts',
@@ -28,6 +24,7 @@ export default class ECharts extends component({
render() {
return (
+ ECharts
雷达图
diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx
index 8dbe017..47ab078 100644
--- a/src/pages/Home.tsx
+++ b/src/pages/Home.tsx
@@ -5,7 +5,7 @@ import { ComponentName } from '../components'
import { Image, Text, View } from '@tarojs/components'
import { imgLogo } from './assets'
import { pageUrls } from '.'
-import { XItem, XList } from './components'
+import { XItem, XList, XNavigationBar } from './components'
interface ComponentInfo {
name: ComponentName,
@@ -80,6 +80,8 @@ export default class Home extends component({
render() {
return (
+ Mounted
+
{/* Logo */}
+ Picker
普通选择
+ PickerView
普通选择
+ Popup
{positionList.map(pos => (
+ SinglePicker
单项选择
+ Sticky
{heroTypeList.map(heroType => (
diff --git a/src/pages/TimePicker.tsx b/src/pages/TimePicker.tsx
index 91c019d..cbcac02 100644
--- a/src/pages/TimePicker.tsx
+++ b/src/pages/TimePicker.tsx
@@ -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 { MTimePicker } 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/U53b3c5ab845b44dcaaa730be547043a8Z.png'
@@ -12,10 +12,6 @@ export default class TimePicker extends component({
selectedTime: [5, 20],
},
}) {
- config: Config = {
- navigationBarTitleText: 'TimePicker',
- }
-
onShareAppMessage(): ShareAppMessageReturn {
return {
title: 'TimePicker',
@@ -27,6 +23,7 @@ export default class TimePicker extends component({
const { selectedTime } = this.state
return (
+ TimePicker
时间选择
-
+ Transition{internalStore.customNavigationBarFullHeight}
+
{transitionNameList.map(name => (
+ {this.props.children}
+
+ )
+ }
+}
diff --git a/src/pages/components/index.ts b/src/pages/components/index.ts
index 7aee0c7..834880d 100644
--- a/src/pages/components/index.ts
+++ b/src/pages/components/index.ts
@@ -3,4 +3,5 @@ export { default as XBackHome } from './BackHome'
export { default as XIcon } from './Icon'
export { default as XItem } from './Item'
export { default as XList } from './List'
+export { default as XNavigationBar } from './NavigationBar'
export { default as XTitle } from './Title'