From 33679d5d2b224838dfc63b0c5ed79200a4ef9d57 Mon Sep 17 00:00:00 2001 From: fxy060608 Date: Thu, 18 Jul 2019 11:27:05 +0800 Subject: [PATCH] feat(app-plus-nvue): refactor route --- packages/uni-app-plus-nvue/dist/index.js | 260 ++++++++++++++---- src/core/service/plugins/util.js | 6 +- .../service/uni/router/navigate-back.js | 2 +- .../service/uni/router/navigate-to.js | 29 +- .../app-plus-nvue/service/uni/router/util.js | 20 -- .../service/uni/router/webview.js | 14 + src/platforms/app-plus/service/uni/bridge.js | 16 ++ src/platforms/app-plus/service/uni/config.js | 3 +- .../service/uni/create-instance-context.js | 17 +- src/platforms/app-plus/service/uni/page.js | 26 +- src/platforms/app-plus/service/uni/webview.js | 52 ++++ 11 files changed, 344 insertions(+), 101 deletions(-) delete mode 100644 src/platforms/app-plus-nvue/service/uni/router/util.js create mode 100644 src/platforms/app-plus-nvue/service/uni/router/webview.js create mode 100644 src/platforms/app-plus/service/uni/bridge.js create mode 100644 src/platforms/app-plus/service/uni/webview.js diff --git a/packages/uni-app-plus-nvue/dist/index.js b/packages/uni-app-plus-nvue/dist/index.js index 822f65e61..ff7ad1b30 100644 --- a/packages/uni-app-plus-nvue/dist/index.js +++ b/packages/uni-app-plus-nvue/dist/index.js @@ -1,48 +1,34 @@ import { createUniInstance } from './uni'; -const ANI_SHOW = 'pop-in'; const ANI_DURATION = 300; +const ANI_SHOW = 'pop-in'; -let id = 0; - -function getId () { - return id++ -} - -function parseWebviewStyle (path) { - return { - titleNView: { - autoBackButton: true, - titleText: 'titleText' - }, - uniNView: { - path - } - } +function showWebview (webview, animationType, animationDuration) { + setTimeout(() => { + webview.show( + animationType || ANI_SHOW, + animationDuration || ANI_DURATION, + () => { + console.log('show.callback'); + } + ); + }, 50); } function initNavigateTo ({ - plus, __registerPage }) { return function navigateTo (path, { animationType, animationDuration }) { - const webview = plus.webview.open( - '', - String(getId()), - parseWebviewStyle(path), - animationType || ANI_SHOW, - animationDuration || ANI_DURATION, - () => { - console.log('show.callback'); - }); - - __registerPage({ - path, - webview - }); + showWebview( + __registerPage({ + path + }), + animationType, + animationDuration + ); } } @@ -139,7 +125,7 @@ class Router { let appCtx; -function getApp () { +function getApp$1 () { return appCtx } @@ -160,9 +146,62 @@ function registerApp (appVm, instanceContext) { initListeners(instanceContext); } +const WEBVIEW_LISTENERS = [ + 'close', + 'resize', + 'popGesture', + 'pullToRefresh', + 'titleNViewSearchInputChanged', + 'titleNViewSearchInputConfirmed', + 'titleNViewSearchInputClicked' +]; + +let id = 1; + +function parseWebviewStyle (path, windowOptions = {}) { + return { + titleNView: { + autoBackButton: true, + titleText: 'titleText' + }, + uniNView: { + path + } + } +} + +function parseWindowOptions (windowOptions = {}, globalWindowOptions = {}) { + // TODO + return windowOptions +} + +function createWebview (path, { + plus, + __uniConfig +}, windowOptions) { + return plus.webview.create( + '', + String(id++), + parseWebviewStyle( + path, + parseWindowOptions(windowOptions, __uniConfig.window) + )) +} + +function initWebview (webview, { + UniJSServiceBridge +}) { + // TODO subNVues + WEBVIEW_LISTENERS.forEach(listener => { + webview.addEventListener(listener, (e) => { + UniJSServiceBridge.emit(listener, e); + }); + }); +} + const pages = []; -function getCurrentPages () { +function getCurrentPages$1 () { return pages } /** @@ -183,23 +222,34 @@ function getCurrentPages () { * * */ - +/** + * 首页需要主动registerPage,二级页面路由跳转时registerPage + */ function registerPage ({ - vm, path, webview }, instanceContext) { + const routeOptions = instanceContext.__uniRoutes.find(route => route.path === path); + + if (!webview) { + webview = createWebview(path, instanceContext, routeOptions.window); + } + if (process.env.NODE_ENV !== 'production') { console.log(`[uni-app] registerPage`, path, webview.id); } + + initWebview(webview, instanceContext, webview.id === '1' && routeOptions.window); + pages.push({ route: path.slice(1), $getAppWebview () { return webview }, - $meta: instanceContext.__uniRoutes.find(route => route.path === path).meta, - $vm: vm - }); + $meta: routeOptions.meta + }); + + return webview } const uniConfig = Object.create(null); @@ -231,23 +281,140 @@ function registerConfig (config) { parseRoutes(uniConfig); } +function callHook (vm, hook, params) { + return (vm.$vm || vm).__call_hook(hook, params) +} + +function callAppHook (vm, hook, params) { + if (hook !== 'onError') { + console.debug(`App:${hook} have been invoked` + (params ? ` ${JSON.stringify(params)}` : '')); + } + return (vm.$vm || vm).__call_hook(hook, params) +} + +function callPageHook (vm, hook, params) { + // hack 一下,H5 平台通知 View 层onShow,方便 View 层来切换 scroll 事件监听 + if (__PLATFORM__ === 'h5') { + if (hook === 'onLoad') { + vm.$mp.query = params; + UniServiceJSBridge.publishHandler('onPageLoad', vm, vm.$page.id); + } + if (hook === 'onShow') { + if ( + vm.$route.meta.isTabBar && + vm.$route.params.detail + ) { + UniServiceJSBridge.emit('onTabItemTap', vm.$route.params.detail); + } + UniServiceJSBridge.publishHandler('onPageShow', vm, vm.$page.id); + } + } + if (hook !== 'onPageScroll') { + console.debug(`${vm.$page.route}[${vm.$page.id}]:${hook} have been invoked`); + } + return callHook(vm, hook, params) +} + +function onError (err) { + callAppHook(getApp(), 'onError', err); +} + +function onPageNotFound (page) { + callAppHook(getApp(), 'onPageNotFound', page); +} + +function onPullDownRefresh (args, pageId) { + const page = getCurrentPages().find(page => page.$page.id === pageId); + if (page) { + callPageHook(page, 'onPullDownRefresh'); + } +} + +function callCurrentPageHook (hook, args) { + const pages = getCurrentPages(); + if (pages.length) { + callPageHook(pages[pages.length - 1], hook, args); + } +} + +function createCallCurrentPageHook (hook) { + return function (args) { + callCurrentPageHook(hook, args); + } +} + +function onAppEnterBackground () { + callAppHook(getApp(), 'onHide'); + callCurrentPageHook('onHide'); +} + +function onAppEnterForeground () { + callAppHook(getApp(), 'onShow'); + callCurrentPageHook('onShow'); +} + +function onWebInvokeAppService ({ + name, + arg +}, pageId) { + if (name === 'postMessage') ; else { + uni[name](arg); + } +} + +function initOn (on) { + on('onError', onError); + on('onPageNotFound', onPageNotFound); + + on('onAppEnterBackground', onAppEnterBackground); + on('onAppEnterForeground', onAppEnterForeground); + + on('onPullDownRefresh', onPullDownRefresh); + + on('onTabItemTap', createCallCurrentPageHook('onTabItemTap')); + on('onNavigationBarButtonTap', createCallCurrentPageHook('onNavigationBarButtonTap')); + + on('onNavigationBarSearchInputChanged', createCallCurrentPageHook('onNavigationBarSearchInputChanged')); + on('onNavigationBarSearchInputConfirmed', createCallCurrentPageHook('onNavigationBarSearchInputConfirmed')); + on('onNavigationBarSearchInputClicked', createCallCurrentPageHook('onNavigationBarSearchInputClicked')); + + on('onWebInvokeAppService', onWebInvokeAppService); +} + +function initServiceJSBridge (Vue) { + const Emitter = new Vue(); + + const bridge = { + on: Emitter.$on.bind(Emitter), + off: Emitter.$off.bind(Emitter), + once: Emitter.$once.bind(Emitter), + emit: Emitter.$emit.bind(Emitter) + }; + + initOn(bridge.on); + + return bridge +} + function createInstanceContext (instanceContext) { const { weex, + Vue, WeexPlus } = instanceContext; const plus = new WeexPlus(weex); + const UniJSServiceBridge = initServiceJSBridge(Vue); return { __uniConfig: uniConfig, __uniRoutes: uniRoutes, __registerConfig (config) { - registerConfig(config, instanceContext); + return registerConfig(config, instanceContext) }, __registerApp (appVm) { - registerApp(appVm, instanceContext); + return registerApp(appVm, instanceContext) }, __registerPage (page) { - registerPage(page, instanceContext); + return registerPage(page, instanceContext) }, plus, uni: createUniInstance( @@ -255,11 +422,12 @@ function createInstanceContext (instanceContext) { plus, uniConfig, uniRoutes, - getApp, - getCurrentPages + getApp$1, + getCurrentPages$1 ), - getApp, - getCurrentPages + getApp: getApp$1, + getCurrentPages: getCurrentPages$1, + UniJSServiceBridge } } diff --git a/src/core/service/plugins/util.js b/src/core/service/plugins/util.js index ed93c3baf..78cfd9dd6 100644 --- a/src/core/service/plugins/util.js +++ b/src/core/service/plugins/util.js @@ -1,12 +1,12 @@ function callHook (vm, hook, params) { - return vm.__call_hook(hook, params) + return (vm.$vm || vm).__call_hook(hook, params) } export function callAppHook (vm, hook, params) { if (hook !== 'onError') { console.debug(`App:${hook} have been invoked` + (params ? ` ${JSON.stringify(params)}` : '')) } - return vm.__call_hook(hook, params) + return (vm.$vm || vm).__call_hook(hook, params) } export function callPageHook (vm, hook, params) { @@ -19,7 +19,7 @@ export function callPageHook (vm, hook, params) { if (hook === 'onShow') { if ( vm.$route.meta.isTabBar && - vm.$route.params.detail + vm.$route.params.detail ) { UniServiceJSBridge.emit('onTabItemTap', vm.$route.params.detail) } diff --git a/src/platforms/app-plus-nvue/service/uni/router/navigate-back.js b/src/platforms/app-plus-nvue/service/uni/router/navigate-back.js index a6f6d8749..1309f16d8 100644 --- a/src/platforms/app-plus-nvue/service/uni/router/navigate-back.js +++ b/src/platforms/app-plus-nvue/service/uni/router/navigate-back.js @@ -1,6 +1,6 @@ import { ANI_DURATION -} from './util' +} from './webview' let firstBackTime = 0 diff --git a/src/platforms/app-plus-nvue/service/uni/router/navigate-to.js b/src/platforms/app-plus-nvue/service/uni/router/navigate-to.js index 827ec2967..6aa5b8495 100644 --- a/src/platforms/app-plus-nvue/service/uni/router/navigate-to.js +++ b/src/platforms/app-plus-nvue/service/uni/router/navigate-to.js @@ -1,31 +1,20 @@ import { - getId, - ANI_SHOW, - ANI_DURATION, - parseWebviewStyle -} from './util' + showWebview +} from './webview' export default function initNavigateTo ({ - plus, __registerPage }) { return function navigateTo (path, { animationType, animationDuration }) { - const webview = plus.webview.open( - '', - String(getId()), - parseWebviewStyle(path), - animationType || ANI_SHOW, - animationDuration || ANI_DURATION, - () => { - console.log('show.callback') - }) - - __registerPage({ - path, - webview - }) + showWebview( + __registerPage({ + path + }), + animationType, + animationDuration + ) } } diff --git a/src/platforms/app-plus-nvue/service/uni/router/util.js b/src/platforms/app-plus-nvue/service/uni/router/util.js deleted file mode 100644 index 55a9801ae..000000000 --- a/src/platforms/app-plus-nvue/service/uni/router/util.js +++ /dev/null @@ -1,20 +0,0 @@ -export const ANI_SHOW = 'pop-in' -export const ANI_DURATION = 300 - -let id = 0 - -export function getId () { - return id++ -} - -export function parseWebviewStyle (path) { - return { - titleNView: { - autoBackButton: true, - titleText: 'titleText' - }, - uniNView: { - path - } - } -} diff --git a/src/platforms/app-plus-nvue/service/uni/router/webview.js b/src/platforms/app-plus-nvue/service/uni/router/webview.js new file mode 100644 index 000000000..992268860 --- /dev/null +++ b/src/platforms/app-plus-nvue/service/uni/router/webview.js @@ -0,0 +1,14 @@ +export const ANI_DURATION = 300 +const ANI_SHOW = 'pop-in' + +export function showWebview (webview, animationType, animationDuration) { + setTimeout(() => { + webview.show( + animationType || ANI_SHOW, + animationDuration || ANI_DURATION, + () => { + console.log('show.callback') + } + ) + }, 50) +} diff --git a/src/platforms/app-plus/service/uni/bridge.js b/src/platforms/app-plus/service/uni/bridge.js new file mode 100644 index 000000000..34d5e3559 --- /dev/null +++ b/src/platforms/app-plus/service/uni/bridge.js @@ -0,0 +1,16 @@ +import initOn from 'uni-core/service/bridge/on' + +export function initServiceJSBridge (Vue) { + const Emitter = new Vue() + + const bridge = { + on: Emitter.$on.bind(Emitter), + off: Emitter.$off.bind(Emitter), + once: Emitter.$once.bind(Emitter), + emit: Emitter.$emit.bind(Emitter) + } + + initOn(bridge.on) + + return bridge +} diff --git a/src/platforms/app-plus/service/uni/config.js b/src/platforms/app-plus/service/uni/config.js index 1d4c510ec..49c3bed15 100644 --- a/src/platforms/app-plus/service/uni/config.js +++ b/src/platforms/app-plus/service/uni/config.js @@ -14,7 +14,8 @@ function parseRoutes (config) { meta: { isQuit, isTabBar - } + }, + window: config.page[pagePath] || {} }) }) } diff --git a/src/platforms/app-plus/service/uni/create-instance-context.js b/src/platforms/app-plus/service/uni/create-instance-context.js index b287b9595..7e1325dc5 100644 --- a/src/platforms/app-plus/service/uni/create-instance-context.js +++ b/src/platforms/app-plus/service/uni/create-instance-context.js @@ -16,25 +16,31 @@ import { import { createUniInstance -} from './uni' +} from './uni' + +import { + initServiceJSBridge +} from './bridge' export function createInstanceContext (instanceContext) { const { weex, + Vue, WeexPlus } = instanceContext const plus = new WeexPlus(weex) + const UniJSServiceBridge = initServiceJSBridge(Vue) return { __uniConfig: uniConfig, __uniRoutes: uniRoutes, __registerConfig (config) { - registerConfig(config, instanceContext) + return registerConfig(config, instanceContext) }, __registerApp (appVm) { - registerApp(appVm, instanceContext) + return registerApp(appVm, instanceContext) }, __registerPage (page) { - registerPage(page, instanceContext) + return registerPage(page, instanceContext) }, plus, uni: createUniInstance( @@ -46,6 +52,7 @@ export function createInstanceContext (instanceContext) { getCurrentPages ), getApp, - getCurrentPages + getCurrentPages, + UniJSServiceBridge } } diff --git a/src/platforms/app-plus/service/uni/page.js b/src/platforms/app-plus/service/uni/page.js index 287c01d04..7c389dd38 100644 --- a/src/platforms/app-plus/service/uni/page.js +++ b/src/platforms/app-plus/service/uni/page.js @@ -1,3 +1,8 @@ +import { + initWebview, + createWebview +} from './webview' + const pages = [] export function getCurrentPages () { @@ -21,21 +26,32 @@ export function getCurrentPages () { * * */ - +/** + * 首页需要主动registerPage,二级页面路由跳转时registerPage + */ export function registerPage ({ - vm, path, webview }, instanceContext) { + const routeOptions = instanceContext.__uniRoutes.find(route => route.path === path) + + if (!webview) { + webview = createWebview(path, instanceContext, routeOptions.window) + } + if (process.env.NODE_ENV !== 'production') { console.log(`[uni-app] registerPage`, path, webview.id) } + + initWebview(webview, instanceContext, webview.id === '1' && routeOptions.window) + pages.push({ route: path.slice(1), $getAppWebview () { return webview }, - $meta: instanceContext.__uniRoutes.find(route => route.path === path).meta, - $vm: vm - }) + $meta: routeOptions.meta + }) + + return webview } diff --git a/src/platforms/app-plus/service/uni/webview.js b/src/platforms/app-plus/service/uni/webview.js new file mode 100644 index 000000000..7387c22c4 --- /dev/null +++ b/src/platforms/app-plus/service/uni/webview.js @@ -0,0 +1,52 @@ +const WEBVIEW_LISTENERS = [ + 'close', + 'resize', + 'popGesture', + 'pullToRefresh', + 'titleNViewSearchInputChanged', + 'titleNViewSearchInputConfirmed', + 'titleNViewSearchInputClicked' +] + +let id = 1 + +function parseWebviewStyle (path, windowOptions = {}) { + return { + titleNView: { + autoBackButton: true, + titleText: 'titleText' + }, + uniNView: { + path + } + } +} + +function parseWindowOptions (windowOptions = {}, globalWindowOptions = {}) { + // TODO + return windowOptions +} + +export function createWebview (path, { + plus, + __uniConfig +}, windowOptions) { + return plus.webview.create( + '', + String(id++), + parseWebviewStyle( + path, + parseWindowOptions(windowOptions, __uniConfig.window) + )) +} + +export function initWebview (webview, { + UniJSServiceBridge +}) { + // TODO subNVues + WEBVIEW_LISTENERS.forEach(listener => { + webview.addEventListener(listener, (e) => { + UniJSServiceBridge.emit(listener, e) + }) + }) +} -- GitLab