-
Notifications
You must be signed in to change notification settings - Fork 389
Feat web title bar #2530
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+282
−0
Merged
Feat web title bar #2530
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
567d6a1
feat: web支持titlebar
mackwang112 e518c9e
docs: web支持titlebar
mackwang112 5832646
refactor: web titlebar 改为在 processTemplate 中按页面插入
mackwang112 6d4d109
refactor: 还原 dom-tag-config 中 isNativeMiniTag 的 titlebar 注册
mackwang112 6ffd46d
fix: defer web titlebar config checks to runtime
mackwang112 2f08ff9
Merge branch 'master' into feat-web-title-bar-mackwang
hiyuki File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
241 changes: 241 additions & 0 deletions
241
packages/webpack-plugin/lib/runtime/components/web/mpx-titlebar.vue
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,241 @@ | ||
| <script> | ||
| import mpx from '@mpxjs/core' | ||
|
|
||
| const safeStyle = { paddingTop: 'var(--safe-area-inset-top)' } | ||
|
|
||
| export default { | ||
| name: 'mpx-titlebar', | ||
| props: { | ||
| // 已合并 app.json window 配置与页面 json 配置的最终配置 | ||
| pageConfig: { | ||
| type: Object, | ||
| default: () => ({}) | ||
| } | ||
| }, | ||
| computed: { | ||
| // 标题文本 | ||
| titleText() { | ||
| return this.pageConfig.navigationBarTitleText || '' | ||
| }, | ||
| // 背景色(兼容常见字段) | ||
| backgroundColor() { | ||
| return this.pageConfig.navigationBarBackgroundColor || '#ffffff' | ||
| }, | ||
| // 文本颜色,微信小程序中 navigationBarTextStyle 为 white 或 black | ||
| textColor() { | ||
| const style = this.pageConfig.navigationBarTextStyle || 'black' | ||
| return style === 'white' ? '#ffffff' : '#000000' | ||
| }, | ||
| // navigationStyle: 'default' | 'custom',custom 表示需要自定义绘制 | ||
| navigationStyle() { | ||
| return this.pageConfig.navigationStyle || 'default' | ||
| }, | ||
| // 是否隐藏(navigationStyle 为 'custom' 时也应隐藏) | ||
| hidden() { | ||
| return mpx.config?.webConfig?.enableTitleBar !== true || this.navigationStyle === 'custom' | ||
| }, | ||
| // 是否展示返回按钮:根据浏览器历史判断(不依赖额外 page 配置) | ||
| showBack() { | ||
| try { | ||
| return this.$router.stack.length > 1 | ||
| } catch (e) { | ||
| return false | ||
| } | ||
| }, | ||
| // 安卓安全高度 | ||
| safeAreaInsetTop() { | ||
| if (typeof mpx.config.webConfig.safeAreaInsetTop === 'number' && mpx.config.webConfig.safeAreaInsetTop >= 0) { | ||
| return mpx.config.webConfig.safeAreaInsetTop | ||
| } | ||
| return 24 | ||
| }, | ||
| isIOS() { | ||
| return /iP(hone|od|ad)/.test(navigator.userAgent) | ||
| }, | ||
| innerHeight() { | ||
| return (this.isIOS ? 44 : 48) + 'px' | ||
| }, | ||
| warpStyle() { | ||
| return { | ||
| '--titlebar-height': this.innerHeight, | ||
| '--safe-area-inset-top': `${this.isIOS ? 'env(safe-area-inset-top, constant(safe-area-inset-top), 0px)' : this.safeAreaInsetTop + 'px'}`, | ||
| paddingTop: 'calc(var(--safe-area-inset-top) + var(--titlebar-height))', | ||
| } | ||
| }, | ||
| rootStyle() { | ||
| return { | ||
| background: this.backgroundColor, | ||
| color: this.textColor | ||
| } | ||
| }, | ||
| innerStyle() { | ||
| return { | ||
| height: this.innerHeight | ||
| } | ||
| } | ||
| }, | ||
| methods: { | ||
| // 左侧点击:派发事件并在可回退时回退 | ||
| onLeftClick(e) { | ||
| this.$emit('click-left', e) | ||
| if (this.showBack) { | ||
| try { window.history.back() } catch (err) { } | ||
| } | ||
| } | ||
| }, | ||
| render(h) { | ||
| const leftChildren = [] | ||
|
|
||
| // default back button (SVG) — no left slot support | ||
| if (this.showBack) { | ||
| leftChildren.push( | ||
| h('button', { | ||
| class: 'mpx-titlebar__back', | ||
| attrs: { 'aria-label': 'back', type: 'button' } | ||
| }, [ | ||
| h('svg', { | ||
| attrs: { | ||
| viewBox: '0 0 24 24', | ||
| width: '20', | ||
| height: '20', | ||
| fill: 'none', | ||
| xmlns: 'http://www.w3.org/2000/svg', | ||
| focusable: 'false', | ||
| 'aria-hidden': 'true' | ||
| } | ||
| }, [ | ||
| h('path', { | ||
| attrs: { | ||
| d: 'M15 18l-6-6 6-6', | ||
| stroke: 'currentColor', | ||
| 'stroke-width': '2', | ||
| 'stroke-linecap': 'round', | ||
| 'stroke-linejoin': 'round' | ||
| } | ||
| }) | ||
| ]) | ||
| ]) | ||
| ) | ||
| } | ||
|
|
||
| // center shows title; only default slot (page content) is supported | ||
| const centerChildren = [ | ||
| h('div', { class: 'mpx-titlebar__title', style: { color: this.textColor } }, [this.titleText]) | ||
| ] | ||
|
|
||
| // top-level wrapper: contains fixed titlebar and page content wrapper | ||
| return h('div', { class: 'mpx-page-warp', style: this.hidden ? {} : this.warpStyle }, [ | ||
| this.hidden ? null : h('div', { | ||
| class: ['mpx-titlebar'], | ||
| style: this.rootStyle | ||
| }, [ | ||
| h('div', { class: 'mpx-titlebar__safe', style: safeStyle }, [ | ||
| h('div', { class: 'mpx-titlebar__inner', style: this.innerStyle }, [ | ||
| h('div', { class: 'mpx-titlebar__left', on: { click: this.onLeftClick } }, leftChildren), | ||
| h('div', { class: 'mpx-titlebar__center' }, centerChildren), | ||
| h('div', { class: 'mpx-titlebar__right' }, []) | ||
| ]) | ||
| ]) | ||
| ]), | ||
| h('page', { style: { position: 'relative'} }, [this.$slots.default]) | ||
| ]) | ||
| } | ||
| } | ||
| </script> | ||
|
|
||
| <style scoped> | ||
| .mpx-page-warp { | ||
| width: 100%; | ||
| height: 100%; | ||
| box-sizing: border-box; | ||
| } | ||
|
|
||
|
|
||
| .mpx-titlebar--hidden { | ||
| display: none; | ||
| } | ||
|
|
||
| .mpx-titlebar__safe { | ||
| padding-top: var(--safe-area-inset-top); | ||
| } | ||
|
|
||
| .mpx-titlebar__inner { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: space-between; | ||
| padding: 0 12px; | ||
| box-sizing: border-box; | ||
| } | ||
|
|
||
| .mpx-titlebar__left, | ||
| .mpx-titlebar__right { | ||
| flex: 0 0 auto; | ||
| min-width: 44px; | ||
| display: flex; | ||
| align-items: center; | ||
| } | ||
|
|
||
| .mpx-titlebar__center { | ||
| flex: 1 1 auto; | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: center; | ||
| overflow: hidden; | ||
| padding: 0 8px; | ||
| } | ||
|
|
||
| .mpx-titlebar__title { | ||
| font-size: 17px; | ||
| white-space: nowrap; | ||
| text-overflow: ellipsis; | ||
| overflow: hidden; | ||
| font-weight: 500; | ||
| } | ||
|
|
||
| .mpx-titlebar__back { | ||
| background: none; | ||
| border: none; | ||
| font-size: 20px; | ||
| color: inherit; | ||
| padding: 6px; | ||
| cursor: pointer; | ||
| } | ||
|
|
||
| .mpx-titlebar { | ||
| /* flex-shrink: 0; */ | ||
| height: calc(var(--safe-area-inset-top) + var(--titlebar-height)); | ||
| width: 100%; | ||
| box-sizing: border-box; | ||
| -webkit-font-smoothing: antialiased; | ||
| position: fixed; | ||
| top: 0; | ||
| left: 0; | ||
| right: 0; | ||
| z-index: 99999; | ||
| /* 脱离上下文,单独渲染加速,修复安卓低端机型在页面滚动时titlebar闪烁问题 */ | ||
| transform: translateZ(0); | ||
| } | ||
|
|
||
| .mpx-titlebar__content { | ||
| flex: 1; | ||
| overflow: hidden; | ||
| transform: translateZ(0); | ||
| } | ||
|
|
||
| .mpx-titlebar__scroll { | ||
| width: 100%; | ||
| height: 100%; | ||
| overflow: auto; | ||
| } | ||
|
|
||
| /* SVG icon sizing and inherit color */ | ||
| .mpx-titlebar__back svg { | ||
| display: block; | ||
| width: 20px; | ||
| height: 20px; | ||
| } | ||
|
|
||
| .mpx-titlebar__back path { | ||
| stroke: currentColor; | ||
| } | ||
| </style> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
加一下ts类型定义