From 1c08837a55c310e27310fab7647da8c8468ba03e Mon Sep 17 00:00:00 2001 From: wangyaqi Date: Fri, 1 Nov 2019 18:23:59 +0800 Subject: [PATCH] fix(v3): subNvue --- .../app-plus/service/framework/app.js | 12 +- .../app-plus/service/framework/backbutton.js | 5 + .../app-plus/service/framework/upx.js | 7 + .../service/framework/webview/index.js | 48 +++++- .../webview/parser/style-unit-parser.js | 20 +++ .../webview/parser/sub-nvue-parser.js | 144 ++++++++++++++++++ .../webview/parser/webview-style-parser.js | 10 +- 7 files changed, 234 insertions(+), 12 deletions(-) create mode 100644 src/platforms/app-plus/service/framework/backbutton.js create mode 100644 src/platforms/app-plus/service/framework/upx.js create mode 100644 src/platforms/app-plus/service/framework/webview/parser/style-unit-parser.js create mode 100644 src/platforms/app-plus/service/framework/webview/parser/sub-nvue-parser.js diff --git a/src/platforms/app-plus/service/framework/app.js b/src/platforms/app-plus/service/framework/app.js index 4b54d60de5..fba82a8ba0 100644 --- a/src/platforms/app-plus/service/framework/app.js +++ b/src/platforms/app-plus/service/framework/app.js @@ -28,7 +28,11 @@ import { import { perf -} from './perf' +} from './perf' + +import { + backbuttonListener +} from './backbutton' let appCtx @@ -39,11 +43,7 @@ export function getApp () { function initGlobalListeners () { const emit = UniServiceJSBridge.emit - plus.key.addEventListener('backbutton', () => { - uni.navigateBack({ - from: 'backbutton' - }) - }) + plus.key.addEventListener('backbutton', backbuttonListener) plus.globalEvent.addEventListener('pause', () => { emit('onAppEnterBackground') diff --git a/src/platforms/app-plus/service/framework/backbutton.js b/src/platforms/app-plus/service/framework/backbutton.js new file mode 100644 index 0000000000..2cda6fe9c4 --- /dev/null +++ b/src/platforms/app-plus/service/framework/backbutton.js @@ -0,0 +1,5 @@ +export function backbuttonListener () { + uni.navigateBack({ + from: 'backbutton' + }) +} diff --git a/src/platforms/app-plus/service/framework/upx.js b/src/platforms/app-plus/service/framework/upx.js new file mode 100644 index 0000000000..efac5784cb --- /dev/null +++ b/src/platforms/app-plus/service/framework/upx.js @@ -0,0 +1,7 @@ +const REGEX_UPX = /(\d+(\.\d+)?)[r|u]px/g + +export function transformCSS (css) { + return css.replace(REGEX_UPX, (a, b) => { + return uni.upx2px(parseInt(b) || 0) + 'px' + }) +} diff --git a/src/platforms/app-plus/service/framework/webview/index.js b/src/platforms/app-plus/service/framework/webview/index.js index 1062885e9b..b366e1e952 100644 --- a/src/platforms/app-plus/service/framework/webview/index.js +++ b/src/platforms/app-plus/service/framework/webview/index.js @@ -1,6 +1,10 @@ import { parseWebviewStyle -} from './parser/webview-style-parser' +} from './parser/webview-style-parser' + +import { + initSubNVues +} from './parser/sub-nvue-parser' import { publish @@ -102,7 +106,7 @@ function onWebviewRecovery (webview, routeOptions) { } subscribe(WEBVIEW_READY, onWebviewRecoveryReady) }) -} +} export function initWebview (webview, routeOptions) { // 首页或非 nvue 页面 @@ -124,7 +128,45 @@ export function initWebview (webview, routeOptions) { emit } = UniServiceJSBridge - // TODO subNVues + // TODO subNVues + initSubNVues(routeOptions,webview) + + // TODO 优化相关依赖性 + // webview.addEventListener('popGesture', e => { + // if (e.type === 'start') { + // // 开始拖拽,还原状态栏前景色 + // this.restoreStatusBarStyle() + // } else if (e.type === 'end' && !e.result) { + // // 拖拽未完成,设置为当前状态栏前景色 + // this.setStatusBarStyle() + // } else if (e.type === 'end' && e.result) { + // removeWebview(this.id) + // const lastWebview = getLastWebview() + // if (lastWebview) { + // publish('onAppRoute', { + // path: lastWebview.page.replace('.html', ''), + // query: {}, + // openType: 'navigateBack', + // webviewId: lastWebview.id + // }) + // } + // } + // }) + + webview.addEventListener('close', () => { + if (this.popupSubNVueWebviews) { // 移除所有 popupSubNVueWebview + Object.keys(this.popupSubNVueWebviews).forEach(id => { + if (process.env.NODE_ENV !== 'production') { + console.log( + `UNIAPP[webview][${this.id}]:popupSubNVueWebview[${id}].close` + ) + } + this.popupSubNVueWebviews[id].close('none') + }) + } + typeof this.closeCallback === 'function' && this.closeCallback() + }) + Object.keys(WEBVIEW_LISTENERS).forEach(name => { webview.addEventListener(name, (e) => { emit(WEBVIEW_LISTENERS[name], e, parseInt(webview.id)) diff --git a/src/platforms/app-plus/service/framework/webview/parser/style-unit-parser.js b/src/platforms/app-plus/service/framework/webview/parser/style-unit-parser.js new file mode 100644 index 0000000000..438f8806d2 --- /dev/null +++ b/src/platforms/app-plus/service/framework/webview/parser/style-unit-parser.js @@ -0,0 +1,20 @@ +import { + transformCSS +} from '../../upx' + +export function parseStyleUnit(styles) { + let newStyles = {} + const stylesStr = JSON.stringify(styles) + if (~stylesStr.indexOf('upx') || ~stylesStr.indexOf('rpx')) { + try { + newStyles = JSON.parse(transformCSS(stylesStr)) + } catch (e) { + newStyles = styles + console.error(e) + } + } else { + newStyles = JSON.parse(stylesStr) + } + + return newStyles +} diff --git a/src/platforms/app-plus/service/framework/webview/parser/sub-nvue-parser.js b/src/platforms/app-plus/service/framework/webview/parser/sub-nvue-parser.js new file mode 100644 index 0000000000..c269b7e3b3 --- /dev/null +++ b/src/platforms/app-plus/service/framework/webview/parser/sub-nvue-parser.js @@ -0,0 +1,144 @@ +import { + TITLEBAR_HEIGHT +} from '../../../constants' + +import { + backbuttonListener +} from '../../backbutton' + +import { + isTabBarPage +} from '../../../bridge' + +function getDefaultFontSize(width) { + return Math.round((width || plus.screen.resolutionWidth) / 20) +} + +function getDefaultViewport() { + return plus.screen.resolutionWidth +} + +function initPopupSubNVue(subNVueWebview, style, maskWebview) { + if (!maskWebview.popupSubNVueWebviews) { + maskWebview.popupSubNVueWebviews = {} + } + + maskWebview.popupSubNVueWebviews[subNVueWebview.id] = subNVueWebview + + if (process.env.NODE_ENV !== 'production') { + console.log( + `UNIAPP[webview][${maskWebview.id}]:add.popupSubNVueWebview[${subNVueWebview.id}]` + ) + } + + const hideSubNVue = function () { + maskWebview.setStyle({ + mask: 'none' + }) + subNVueWebview.hide('auto') + } + maskWebview.addEventListener('maskClick', hideSubNVue) + let isRemoved = false // 增加个 remove 标记,防止出错 + subNVueWebview.addEventListener('show', () => { + if (!isRemoved) { + plus.key.removeEventListener('backbutton', backbuttonListener) + plus.key.addEventListener('backbutton', hideSubNVue) + isRemoved = true + } + }) + subNVueWebview.addEventListener('hide', () => { + if (isRemoved) { + plus.key.removeEventListener('backbutton', hideSubNVue) + plus.key.addEventListener('backbutton', backbuttonListener) + isRemoved = false + } + }) + subNVueWebview.addEventListener('close', () => { + delete maskWebview.popupSubNVueWebviews[subNVueWebview.id] + if (isRemoved) { + plus.key.removeEventListener('backbutton', hideSubNVue) + plus.key.addEventListener('backbutton', backbuttonListener) + isRemoved = false + } + }) +} + +function initNormalSubNVue(subNVueWebview, style, webview) { + webview.append(subNVueWebview) +} + +function initSubNVue(subNVue,routeOptions,webview) { + if (!subNVue.path) { + return + } + const style = subNVue.style || {} // 格式化 + const isNavigationBar = subNVue.type === 'navigationBar' + const isPopup = subNVue.type === 'popup' + + delete style.type + + if (isPopup && !subNVue.id) { + console.warn('subNVue[' + subNVue.path + '] 尚未配置 id') + } + // TODO lazyload + + style.uniNView = { + path: subNVue.path.replace('.nvue', '.js'), + defaultFontSize: getDefaultFontSize(), + viewport: getDefaultViewport() + } + + const extras = { + __uniapp_host: routeOptions.path, + __uniapp_origin: style.uniNView.path.split('?')[0].replace('.js', ''), + __uniapp_origin_id: webview.id, + __uniapp_origin_type: webview.__uniapp_type + } + + let maskWebview + + if (isNavigationBar) { + style.position = 'dock' + style.dock = 'top' + style.top = 0 + style.width = '100%' + style.height = TITLEBAR_HEIGHT + plus.navigator.getStatusbarHeight() + delete style.left + delete style.right + delete style.bottom + delete style.margin + } else if (isPopup) { + style.position = 'absolute' + console.log(isTabBarPage(routeOptions.path)); + if (isTabBarPage(routeOptions.path)) { + maskWebview = tabBar + } else { + maskWebview = webview + } + extras.__uniapp_mask = style.mask || 'rgba(0,0,0,0.5)' + extras.__uniapp_mask_id = maskWebview.id + } + + if (process.env.NODE_ENV !== 'production') { + console.log( + `UNIAPP[webview][${webview.id}]:create[${subNVue.id}]:${JSON.stringify(style)}` + ) + } + const subNVueWebview = plus.webview.create('', subNVue.id, style, extras) + + if (isPopup) { + initPopupSubNVue(subNVueWebview, style, maskWebview) + } else { + initNormalSubNVue(subNVueWebview, style, webview) + } +} + +export function initSubNVues(routeOptions,webview) { + const subNVues = routeOptions.window.subNVues + if (!subNVues || !subNVues.length) { + return + } + subNVues.forEach(subNVue => { + initSubNVue(subNVue,routeOptions,webview) + }) +} diff --git a/src/platforms/app-plus/service/framework/webview/parser/webview-style-parser.js b/src/platforms/app-plus/service/framework/webview/parser/webview-style-parser.js index 1b6f1e1772..937b9a4649 100644 --- a/src/platforms/app-plus/service/framework/webview/parser/webview-style-parser.js +++ b/src/platforms/app-plus/service/framework/webview/parser/webview-style-parser.js @@ -4,7 +4,11 @@ import { import { parsePullToRefresh -} from './pull-to-refresh-parser' +} from './pull-to-refresh-parser' + +import { + parseStyleUnit +} from './style-unit-parser' const WEBVIEW_STYLE_BLACKLIST = [ 'navigationBarBackgroundColor', @@ -27,10 +31,10 @@ export function parseWebviewStyle (id, path, routeOptions = {}) { const webviewStyle = Object.create(null) // 合并 - routeOptions.window = Object.assign( + routeOptions.window = parseStyleUnit(Object.assign( JSON.parse(JSON.stringify(__uniConfig.window || {})), routeOptions.window || {} - ) + )) Object.keys(routeOptions.window).forEach(name => { if (WEBVIEW_STYLE_BLACKLIST.indexOf(name) === -1) { -- GitLab