From 2d30a9250160a5c0ed5439d18c17e2c2f28ea7b0 Mon Sep 17 00:00:00 2001 From: fxy060608 Date: Wed, 17 Jul 2019 19:14:52 +0800 Subject: [PATCH] feat(app-plus-nvue): add route --- .editorconfig | 2 +- packages/uni-app-plus-nvue/dist/index.js | 216 ++++++++++++++---- packages/uni-app-plus-nvue/dist/uni.js | 63 ++++- src/core/helpers/protocol/route.js | 52 ++++- src/core/service/api/route.js | 11 +- .../app-plus-nvue/service/uni/router.js | 45 ---- .../app-plus-nvue/service/uni/router/index.js | 44 ++++ .../service/uni/router/navigate-back.js | 37 +++ .../service/uni/router/navigate-to.js | 31 +++ .../service/uni/router/re-launch.js | 5 + .../service/uni/router/redirect-to.js | 5 + .../service/uni/router/switch-tab.js | 5 + .../app-plus-nvue/service/uni/router/util.js | 20 ++ src/platforms/app-plus/service/uni/app.js | 18 +- src/platforms/app-plus/service/uni/config.js | 10 +- .../service/uni/create-instance-context.js | 22 +- src/platforms/app-plus/service/uni/page.js | 23 +- 17 files changed, 485 insertions(+), 124 deletions(-) delete mode 100644 src/platforms/app-plus-nvue/service/uni/router.js create mode 100644 src/platforms/app-plus-nvue/service/uni/router/index.js create mode 100644 src/platforms/app-plus-nvue/service/uni/router/navigate-back.js create mode 100644 src/platforms/app-plus-nvue/service/uni/router/navigate-to.js create mode 100644 src/platforms/app-plus-nvue/service/uni/router/re-launch.js create mode 100644 src/platforms/app-plus-nvue/service/uni/router/redirect-to.js create mode 100644 src/platforms/app-plus-nvue/service/uni/router/switch-tab.js create mode 100644 src/platforms/app-plus-nvue/service/uni/router/util.js diff --git a/.editorconfig b/.editorconfig index 1b0191187..d0d3054ab 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,7 +6,7 @@ root = true [*] charset = utf-8 indent_style = space -indent_size = 4 +indent_size = 2 end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true diff --git a/packages/uni-app-plus-nvue/dist/index.js b/packages/uni-app-plus-nvue/dist/index.js index 1e82232cc..822f65e61 100644 --- a/packages/uni-app-plus-nvue/dist/index.js +++ b/packages/uni-app-plus-nvue/dist/index.js @@ -1,48 +1,139 @@ import { createUniInstance } from './uni'; -function getWebviewStyle () { +const ANI_SHOW = 'pop-in'; +const ANI_DURATION = 300; + +let id = 0; + +function getId () { + return id++ +} + +function parseWebviewStyle (path) { return { titleNView: { autoBackButton: true, titleText: 'titleText' + }, + uniNView: { + path } } -} -class Router { - constructor (routes, plus) { - this.routes = routes; - this.plus = plus; - this.id = 0; - - this.aniShow = plus.os.name === 'Android' ? 'slide-in-right' : 'pop-in'; - this.aniClose = 'pop-out'; - this.aniDuration = 300; - } - - push ({ - type, - path - } = {}) { - this.plus.webview.open( +} + +function initNavigateTo ({ + plus, + __registerPage +}) { + return function navigateTo (path, { + animationType, + animationDuration + }) { + const webview = plus.webview.open( '', - String(this.id++), - getWebviewStyle(), - this.aniShow, - this.aniDuration, + String(getId()), + parseWebviewStyle(path), + animationType || ANI_SHOW, + animationDuration || ANI_DURATION, () => { console.log('show.callback'); }); + + __registerPage({ + path, + webview + }); } +} + +function initRedirectTo () { + return function redirectTo (path) { - replace ({ - type, - path - } = {}) { + } +} + +let firstBackTime = 0; + +function initNavigateBack ({ + plus, + getCurrentPages +}) { + return function navigateBack (delta, { + animationType, + animationDuration + }) { + const pages = getCurrentPages(); + const len = pages.length - 1; + const page = pages[len]; + if (page.$meta.isQuit) { + if (!firstBackTime) { + firstBackTime = Date.now(); + plus.nativeUI.toast('再按一次退出应用'); + setTimeout(() => { + firstBackTime = null; + }, 2000); + } else if (Date.now() - firstBackTime < 2000) { + plus.runtime.quit(); + } + } else { + pages.splice(len, 1); + if (animationType) { + page.$getAppWebview().close(animationType, animationDuration || ANI_DURATION); + } else { + page.$getAppWebview().close('auto'); + } + } + } +} + +function initSwitchTab (path) { + return function switchTab () { } +} + +function initReLaunch () { + return function reLaunch (path) { - go (delta) { + } +} + +function initRouter (instanceContext) { + return { + navigateTo: initNavigateTo(instanceContext), + redirectTo: initRedirectTo(instanceContext), + navigateBack: initNavigateBack(instanceContext), + switchTab: initSwitchTab(instanceContext), + reLaunch: initReLaunch(instanceContext) + } +} + +class Router { + constructor (instanceContext) { + this.router = initRouter(instanceContext); + } + + push ({ + type, + path, + animationType, + animationDuration + } = {}) { + this.router[type](path, { + animationType, + animationDuration + }); + } + go (delta, { + animationType, + animationDuration + } = {}) { + delta = Math.abs(parseInt(delta) || 1); + this.router.navigateBack(delta, { + animationType, + animationDuration + }); } } @@ -52,15 +143,27 @@ function getApp () { return appCtx } -function registerApp (appVm, routes, plus) { +function initListeners ({ + plus +}) { + plus.key.addEventListener('backbutton', () => { + appCtx.$router.go(-1); + }); +} + +function registerApp (appVm, instanceContext) { + if (process.env.NODE_ENV !== 'production') { + console.log(`[uni-app] registerApp`); + } appCtx = appVm; - appCtx.$router = new Router(routes, plus); + appCtx.$router = new Router(instanceContext); + initListeners(instanceContext); } -const pageVms = []; +const pages = []; function getCurrentPages () { - return pageVms + return pages } /** * @param {Object} pageVm @@ -80,55 +183,78 @@ function getCurrentPages () { * * */ -function registerPage (pageVm) { - pageVms.push(pageVm); + +function registerPage ({ + vm, + path, + webview +}, instanceContext) { + if (process.env.NODE_ENV !== 'production') { + console.log(`[uni-app] registerPage`, path, webview.id); + } + pages.push({ + route: path.slice(1), + $getAppWebview () { + return webview + }, + $meta: instanceContext.__uniRoutes.find(route => route.path === path).meta, + $vm: vm + }); } const uniConfig = Object.create(null); const uniRoutes = []; function parseRoutes (config) { - uniRoutes.length = 0; + uniRoutes.length = 0; /* eslint-disable no-mixed-operators */ const tabBarList = (config.tabBar && config.tabBar.list || []).map(item => item.pagePath); Object.keys(config.page).forEach(function (pagePath) { + const isTabBar = tabBarList.indexOf(pagePath) !== -1; + const isQuit = isTabBar || (config.pages[0] === pagePath); uniRoutes.push({ path: '/' + pagePath, meta: { - isTabBar: tabBarList.indexOf(pagePath) !== -1 + isQuit, + isTabBar } }); }); } function registerConfig (config) { + if (process.env.NODE_ENV !== 'production') { + console.log(`[uni-app] registerConfig`); + } Object.assign(uniConfig, config); parseRoutes(uniConfig); } -function createInstanceContext ({ - weex, - WeexPlus -}) { +function createInstanceContext (instanceContext) { + const { + weex, + WeexPlus + } = instanceContext; const plus = new WeexPlus(weex); return { __uniConfig: uniConfig, __uniRoutes: uniRoutes, __registerConfig (config) { - registerConfig(config); + registerConfig(config, instanceContext); }, __registerApp (appVm) { - registerApp(appVm, uniRoutes, plus); + registerApp(appVm, instanceContext); }, - __registerPage (pageVm) { - registerPage(pageVm); + __registerPage (page) { + registerPage(page, instanceContext); }, + plus, uni: createUniInstance( weex, plus, - __uniConfig, - __uniRoutes, + uniConfig, + uniRoutes, getApp, getCurrentPages ), diff --git a/packages/uni-app-plus-nvue/dist/uni.js b/packages/uni-app-plus-nvue/dist/uni.js index bac3cfae5..8f04463d6 100644 --- a/packages/uni-app-plus-nvue/dist/uni.js +++ b/packages/uni-app-plus-nvue/dist/uni.js @@ -1136,24 +1136,54 @@ function createValidator (type) { } } -function createProtocol (type) { - return { +function createProtocol (type, extras = {}) { + return Object.assign({ url: { type: String, required: true, validator: createValidator(type) } + }, extras) +} + +function createAnimationProtocol (animationTypes) { + return { + animationType: { + type: String, + validator (type) { + if (type && animationTypes.indexOf(type) === -1) { + return '`' + type + '` is not supported for `animationType` (supported values are: `' + animationTypes.join( + '`|`') + '`)' + } + } + }, + animationDuration: { + type: Number + } } } + const redirectTo = createProtocol('redirectTo'); const reLaunch = createProtocol('reLaunch'); -const navigateTo = createProtocol('navigateTo'); +const navigateTo = createProtocol('navigateTo', createAnimationProtocol( + [ + 'slide-in-right', + 'slide-in-left', + 'slide-in-top', + 'slide-in-bottom', + 'fade-in', + 'zoom-out', + 'zoom-fade-out', + 'pop-in', + 'none' + ] +)); const switchTab = createProtocol('switchTab'); -const navigateBack = { +const navigateBack = Object.assign({ delta: { type: Number, validator (delta, params) { @@ -1161,7 +1191,19 @@ const navigateBack = { params.delta = Math.min(getCurrentPages().length - 1, delta); } } -}; +}, createAnimationProtocol( + [ + 'slide-out-right', + 'slide-out-left', + 'slide-out-top', + 'slide-out-bottom', + 'fade-out', + 'zoom-in', + 'zoom-fade-in', + 'pop-out', + 'none' + ] +)); var require_context_module_0_19 = /*#__PURE__*/Object.freeze({ redirectTo: redirectTo, @@ -1735,6 +1777,8 @@ function hasLifecycleHook (vueOptions = {}, hook) { function onAppRoute (type, { url, delta, + animationType, + animationDuration, from = 'navigateBack', detail } = {}) { @@ -1749,7 +1793,9 @@ function onAppRoute (type, { case 'navigateTo': router.push({ type, - path: url + path: url, + animationType, + animationDuration }); break case 'navigateBack': @@ -1767,7 +1813,10 @@ function onAppRoute (type, { if (delta > 1) { router._$delta = delta; } - router.go(-delta); + router.go(-delta, { + animationType, + animationDuration + }); } break case 'reLaunch': diff --git a/src/core/helpers/protocol/route.js b/src/core/helpers/protocol/route.js index 312a325ec..26b54a1de 100644 --- a/src/core/helpers/protocol/route.js +++ b/src/core/helpers/protocol/route.js @@ -75,24 +75,54 @@ function createValidator (type) { } } -function createProtocol (type) { - return { +function createProtocol (type, extras = {}) { + return Object.assign({ url: { type: String, required: true, validator: createValidator(type) } + }, extras) +} + +function createAnimationProtocol (animationTypes) { + return { + animationType: { + type: String, + validator (type) { + if (type && animationTypes.indexOf(type) === -1) { + return '`' + type + '` is not supported for `animationType` (supported values are: `' + animationTypes.join( + '`|`') + '`)' + } + } + }, + animationDuration: { + type: Number + } } } + export const redirectTo = createProtocol('redirectTo') export const reLaunch = createProtocol('reLaunch') -export const navigateTo = createProtocol('navigateTo') +export const navigateTo = createProtocol('navigateTo', createAnimationProtocol( + [ + 'slide-in-right', + 'slide-in-left', + 'slide-in-top', + 'slide-in-bottom', + 'fade-in', + 'zoom-out', + 'zoom-fade-out', + 'pop-in', + 'none' + ] +)) export const switchTab = createProtocol('switchTab') -export const navigateBack = { +export const navigateBack = Object.assign({ delta: { type: Number, validator (delta, params) { @@ -100,4 +130,16 @@ export const navigateBack = { params.delta = Math.min(getCurrentPages().length - 1, delta) } } -} +}, createAnimationProtocol( + [ + 'slide-out-right', + 'slide-out-left', + 'slide-out-top', + 'slide-out-bottom', + 'fade-out', + 'zoom-in', + 'zoom-fade-in', + 'pop-out', + 'none' + ] +)) diff --git a/src/core/service/api/route.js b/src/core/service/api/route.js index 0559df84c..3c8cc8f1c 100644 --- a/src/core/service/api/route.js +++ b/src/core/service/api/route.js @@ -5,6 +5,8 @@ import { function onAppRoute (type, { url, delta, + animationType, + animationDuration, from = 'navigateBack', detail } = {}) { @@ -19,7 +21,9 @@ function onAppRoute (type, { case 'navigateTo': router.push({ type, - path: url + path: url, + animationType, + animationDuration }) break case 'navigateBack': @@ -37,7 +41,10 @@ function onAppRoute (type, { if (delta > 1) { router._$delta = delta } - router.go(-delta) + router.go(-delta, { + animationType, + animationDuration + }) } break case 'reLaunch': diff --git a/src/platforms/app-plus-nvue/service/uni/router.js b/src/platforms/app-plus-nvue/service/uni/router.js deleted file mode 100644 index 0d54a1bd6..000000000 --- a/src/platforms/app-plus-nvue/service/uni/router.js +++ /dev/null @@ -1,45 +0,0 @@ -function getWebviewStyle () { - return { - titleNView: { - autoBackButton: true, - titleText: 'titleText' - } - } -} -export default class Router { - constructor (routes, plus) { - this.routes = routes - this.plus = plus - this.id = 0 - - this.aniShow = plus.os.name === 'Android' ? 'slide-in-right' : 'pop-in' - this.aniClose = 'pop-out' - this.aniDuration = 300 - } - - push ({ - type, - path - } = {}) { - this.plus.webview.open( - '', - String(this.id++), - getWebviewStyle(), - this.aniShow, - this.aniDuration, - () => { - console.log('show.callback') - }) - } - - replace ({ - type, - path - } = {}) { - - } - - go (delta) { - - } -} diff --git a/src/platforms/app-plus-nvue/service/uni/router/index.js b/src/platforms/app-plus-nvue/service/uni/router/index.js new file mode 100644 index 000000000..3cad21561 --- /dev/null +++ b/src/platforms/app-plus-nvue/service/uni/router/index.js @@ -0,0 +1,44 @@ +import initNavigateTo from './navigate-to' +import initRedirectTo from './redirect-to' +import initNavigateBack from './navigate-back' +import initSwitchTab from './switch-tab' +import initReLaunch from './re-launch' + +function initRouter (instanceContext) { + return { + navigateTo: initNavigateTo(instanceContext), + redirectTo: initRedirectTo(instanceContext), + navigateBack: initNavigateBack(instanceContext), + switchTab: initSwitchTab(instanceContext), + reLaunch: initReLaunch(instanceContext) + } +} + +export default class Router { + constructor (instanceContext) { + this.router = initRouter(instanceContext) + } + + push ({ + type, + path, + animationType, + animationDuration + } = {}) { + this.router[type](path, { + animationType, + animationDuration + }) + } + + go (delta, { + animationType, + animationDuration + } = {}) { + delta = Math.abs(parseInt(delta) || 1) + this.router.navigateBack(delta, { + animationType, + animationDuration + }) + } +} 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 new file mode 100644 index 000000000..a6f6d8749 --- /dev/null +++ b/src/platforms/app-plus-nvue/service/uni/router/navigate-back.js @@ -0,0 +1,37 @@ +import { + ANI_DURATION +} from './util' + +let firstBackTime = 0 + +export default function initNavigateBack ({ + plus, + getCurrentPages +}) { + return function navigateBack (delta, { + animationType, + animationDuration + }) { + const pages = getCurrentPages() + const len = pages.length - 1 + const page = pages[len] + if (page.$meta.isQuit) { + if (!firstBackTime) { + firstBackTime = Date.now() + plus.nativeUI.toast('再按一次退出应用') + setTimeout(() => { + firstBackTime = null + }, 2000) + } else if (Date.now() - firstBackTime < 2000) { + plus.runtime.quit() + } + } else { + pages.splice(len, 1) + if (animationType) { + page.$getAppWebview().close(animationType, animationDuration || ANI_DURATION) + } else { + page.$getAppWebview().close('auto') + } + } + } +} 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 new file mode 100644 index 000000000..827ec2967 --- /dev/null +++ b/src/platforms/app-plus-nvue/service/uni/router/navigate-to.js @@ -0,0 +1,31 @@ +import { + getId, + ANI_SHOW, + ANI_DURATION, + parseWebviewStyle +} from './util' + +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 + }) + } +} diff --git a/src/platforms/app-plus-nvue/service/uni/router/re-launch.js b/src/platforms/app-plus-nvue/service/uni/router/re-launch.js new file mode 100644 index 000000000..3655c4510 --- /dev/null +++ b/src/platforms/app-plus-nvue/service/uni/router/re-launch.js @@ -0,0 +1,5 @@ +export default function initReLaunch () { + return function reLaunch (path) { + + } +} diff --git a/src/platforms/app-plus-nvue/service/uni/router/redirect-to.js b/src/platforms/app-plus-nvue/service/uni/router/redirect-to.js new file mode 100644 index 000000000..7ebe04f5d --- /dev/null +++ b/src/platforms/app-plus-nvue/service/uni/router/redirect-to.js @@ -0,0 +1,5 @@ +export default function initRedirectTo () { + return function redirectTo (path) { + + } +} diff --git a/src/platforms/app-plus-nvue/service/uni/router/switch-tab.js b/src/platforms/app-plus-nvue/service/uni/router/switch-tab.js new file mode 100644 index 000000000..d52a0bf58 --- /dev/null +++ b/src/platforms/app-plus-nvue/service/uni/router/switch-tab.js @@ -0,0 +1,5 @@ +export default function initSwitchTab (path) { + return function switchTab () { + + } +} diff --git a/src/platforms/app-plus-nvue/service/uni/router/util.js b/src/platforms/app-plus-nvue/service/uni/router/util.js new file mode 100644 index 000000000..55a9801ae --- /dev/null +++ b/src/platforms/app-plus-nvue/service/uni/router/util.js @@ -0,0 +1,20 @@ +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/service/uni/app.js b/src/platforms/app-plus/service/uni/app.js index 123bd2be8..43ac64735 100644 --- a/src/platforms/app-plus/service/uni/app.js +++ b/src/platforms/app-plus/service/uni/app.js @@ -1,4 +1,4 @@ -import Router from 'uni-platform/service/uni/router' +import Router from 'uni-platform/service/uni/router/index' let appCtx @@ -6,7 +6,19 @@ export function getApp () { return appCtx } -export function registerApp (appVm, routes, plus) { +function initListeners ({ + plus +}) { + plus.key.addEventListener('backbutton', () => { + appCtx.$router.go(-1) + }) +} + +export function registerApp (appVm, instanceContext) { + if (process.env.NODE_ENV !== 'production') { + console.log(`[uni-app] registerApp`) + } appCtx = appVm - appCtx.$router = new Router(routes, plus) + appCtx.$router = new Router(instanceContext) + initListeners(instanceContext) } diff --git a/src/platforms/app-plus/service/uni/config.js b/src/platforms/app-plus/service/uni/config.js index f5287356f..1d4c510ec 100644 --- a/src/platforms/app-plus/service/uni/config.js +++ b/src/platforms/app-plus/service/uni/config.js @@ -2,21 +2,27 @@ export const uniConfig = Object.create(null) export const uniRoutes = [] function parseRoutes (config) { - uniRoutes.length = 0 + uniRoutes.length = 0 /* eslint-disable no-mixed-operators */ const tabBarList = (config.tabBar && config.tabBar.list || []).map(item => item.pagePath) Object.keys(config.page).forEach(function (pagePath) { + const isTabBar = tabBarList.indexOf(pagePath) !== -1 + const isQuit = isTabBar || (config.pages[0] === pagePath) uniRoutes.push({ path: '/' + pagePath, meta: { - isTabBar: tabBarList.indexOf(pagePath) !== -1 + isQuit, + isTabBar } }) }) } export function registerConfig (config) { + if (process.env.NODE_ENV !== 'production') { + console.log(`[uni-app] registerConfig`) + } Object.assign(uniConfig, config) parseRoutes(uniConfig) } 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 02c0d1150..b287b9595 100644 --- a/src/platforms/app-plus/service/uni/create-instance-context.js +++ b/src/platforms/app-plus/service/uni/create-instance-context.js @@ -18,28 +18,30 @@ import { createUniInstance } from './uni' -export function createInstanceContext ({ - weex, - WeexPlus -}) { +export function createInstanceContext (instanceContext) { + const { + weex, + WeexPlus + } = instanceContext const plus = new WeexPlus(weex) return { __uniConfig: uniConfig, __uniRoutes: uniRoutes, __registerConfig (config) { - registerConfig(config) + registerConfig(config, instanceContext) }, __registerApp (appVm) { - registerApp(appVm, uniRoutes, plus) + registerApp(appVm, instanceContext) }, - __registerPage (pageVm) { - registerPage(pageVm) + __registerPage (page) { + registerPage(page, instanceContext) }, + plus, uni: createUniInstance( weex, plus, - __uniConfig, - __uniRoutes, + uniConfig, + uniRoutes, getApp, getCurrentPages ), diff --git a/src/platforms/app-plus/service/uni/page.js b/src/platforms/app-plus/service/uni/page.js index 4adb1d0b4..287c01d04 100644 --- a/src/platforms/app-plus/service/uni/page.js +++ b/src/platforms/app-plus/service/uni/page.js @@ -1,7 +1,7 @@ -const pageVms = [] +const pages = [] export function getCurrentPages () { - return pageVms + return pages } /** * @param {Object} pageVm @@ -21,6 +21,21 @@ export function getCurrentPages () { * * */ -export function registerPage (pageVm) { - pageVms.push(pageVm) + +export function registerPage ({ + vm, + path, + webview +}, instanceContext) { + if (process.env.NODE_ENV !== 'production') { + console.log(`[uni-app] registerPage`, path, webview.id) + } + pages.push({ + route: path.slice(1), + $getAppWebview () { + return webview + }, + $meta: instanceContext.__uniRoutes.find(route => route.path === path).meta, + $vm: vm + }) } -- GitLab