From 9550e4b59224c99e7ba45283a5c84c17593dc11a Mon Sep 17 00:00:00 2001 From: DCloud_LXH <283700113@qq.com> Date: Fri, 30 Jul 2021 17:39:58 +0800 Subject: [PATCH] =?UTF-8?q?feat(App):=20preloadPage=E3=80=81unPreloadPage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../uni-app-plus/src/service/api/index.ts | 1 + .../src/service/api/route/preloadPage.ts | 56 +++++++++++++++ .../src/service/api/route/redirectTo.ts | 11 +-- .../src/service/framework/page/preLoad.ts | 68 +++++++++++++++++++ .../src/service/framework/page/register.ts | 34 +++++++++- 5 files changed, 163 insertions(+), 7 deletions(-) create mode 100644 packages/uni-app-plus/src/service/api/route/preloadPage.ts create mode 100644 packages/uni-app-plus/src/service/framework/page/preLoad.ts diff --git a/packages/uni-app-plus/src/service/api/index.ts b/packages/uni-app-plus/src/service/api/index.ts index b09ed08bf..fef8a81ac 100644 --- a/packages/uni-app-plus/src/service/api/index.ts +++ b/packages/uni-app-plus/src/service/api/index.ts @@ -66,6 +66,7 @@ export * from './route/navigateTo' export * from './route/redirectTo' export * from './route/reLaunch' export * from './route/switchTab' +export * from './route/preloadPage' export { upx2px, diff --git a/packages/uni-app-plus/src/service/api/route/preloadPage.ts b/packages/uni-app-plus/src/service/api/route/preloadPage.ts new file mode 100644 index 000000000..d7c4ce3b2 --- /dev/null +++ b/packages/uni-app-plus/src/service/api/route/preloadPage.ts @@ -0,0 +1,56 @@ +import { parseQuery } from '@dcloudio/uni-shared' +import { + API_PRELOAD_PAGE, + API_TYPE_PRELOAD_PAGE, + PreloadPageProtocol, + API_UN_PRELOAD_PAGE, + API_TYPE_UN_PRELOAD_PAGE, + UnPreloadPageProtocol, + defineAsyncApi, + defineSyncApi, +} from '@dcloudio/uni-api' +import { + preloadWebview, + closePreloadWebview, +} from '../../framework/page/preLoad' + +export const unPreloadPage = defineSyncApi( + API_UN_PRELOAD_PAGE, + ({ url }) => { + const webview = closePreloadWebview({ + url, + }) + if (webview) { + return { + id: webview.id, + url, + errMsg: 'unPreloadPage:ok', + } + } + return { + url, + errMsg: 'unPreloadPage:fail not found', + } + }, + UnPreloadPageProtocol +) + +export const preloadPage = defineAsyncApi( + API_PRELOAD_PAGE, + ({ url }, { resolve, reject }) => { + const urls = url.split('?') + const path = urls[0] + const query = parseQuery(urls[1] || '') + const webview = preloadWebview({ + url, + path, + query, + }) + resolve({ + id: webview.id, + url, + errMsg: 'preloadPage:ok', + }) + }, + PreloadPageProtocol +) diff --git a/packages/uni-app-plus/src/service/api/route/redirectTo.ts b/packages/uni-app-plus/src/service/api/route/redirectTo.ts index f4ea030d5..02682d58b 100644 --- a/packages/uni-app-plus/src/service/api/route/redirectTo.ts +++ b/packages/uni-app-plus/src/service/api/route/redirectTo.ts @@ -13,6 +13,10 @@ import { navigate, RouteOptions } from './utils' import { showWebview } from './webview' import { setStatusBarStyle } from '../../statusBar' import { ComponentPublicInstance } from 'vue' +import { + removePreloadWebview, + PreloadWebviewObject, +} from '../../framework/page/preLoad' export const redirectTo = defineAsyncApi( API_REDIRECT_TO, @@ -73,10 +77,9 @@ function _redirectTo({ if (lastPage) { const webview = (lastPage as ComponentPublicInstance) .$getAppWebview!() - // TODO preload - // if (webview.__preload__) { - // removePreloadWebview(webview) - // } + if ((webview as PreloadWebviewObject).__preload__) { + removePreloadWebview(webview) + } webview.close('none') } resolve(undefined) diff --git a/packages/uni-app-plus/src/service/framework/page/preLoad.ts b/packages/uni-app-plus/src/service/framework/page/preLoad.ts new file mode 100644 index 000000000..3a3750e05 --- /dev/null +++ b/packages/uni-app-plus/src/service/framework/page/preLoad.ts @@ -0,0 +1,68 @@ +import { ComponentPublicInstance } from 'vue' +import { createWebview } from '../webview' + +export interface PreloadWebviewObject extends PlusWebviewWebviewObject { + __preload__?: boolean + __query__?: string + __page__?: ComponentPublicInstance +} + +export const preloadWebviews: Record = {} + +export function removePreloadWebview(webview: PreloadWebviewObject) { + const url = Object.keys(preloadWebviews).find( + (url) => preloadWebviews[url].id === webview.id + ) + if (url) { + if (process.env.NODE_ENV !== 'production') { + console.log(`[uni-app] removePreloadWebview(${webview.id})`) + } + delete preloadWebviews[url] + } +} + +export function closePreloadWebview({ url }: { url: string }) { + const webview = preloadWebviews[url] + if (webview) { + if (webview.__page__) { + if (!getCurrentPages().find((page) => page === webview.__page__)) { + // 未使用 + webview.close('none') + } else { + // 被使用 + webview.__preload__ = false + } + } else { + // 未使用 + webview.close('none') + } + delete preloadWebviews[url] + } + return webview +} + +export function preloadWebview({ + url, + path, + query, +}: { + url: string + path: string + query: Record +}) { + if (!preloadWebviews[url]) { + const routeOptions: UniApp.UniRoute = JSON.parse( + JSON.stringify(__uniRoutes.find((route) => route.path === path)) + ) + preloadWebviews[url] = createWebview({ + path, + routeOptions, + query, + webviewStyle: { + __preload__: true, + __query__: JSON.stringify(query), + }, + }) + } + return preloadWebviews[url] +} diff --git a/packages/uni-app-plus/src/service/framework/page/register.ts b/packages/uni-app-plus/src/service/framework/page/register.ts index b00d41ae3..675e49f56 100644 --- a/packages/uni-app-plus/src/service/framework/page/register.ts +++ b/packages/uni-app-plus/src/service/framework/page/register.ts @@ -6,7 +6,7 @@ import { ON_REACH_BOTTOM_DISTANCE, PageNodeOptions, } from '@dcloudio/uni-shared' -import { initPageInternalInstance } from '@dcloudio/uni-core' +import { initPageInternalInstance, initPageVm } from '@dcloudio/uni-core' import { initEntry } from '../app/initEntry' import { initRouteOptions } from './routeOptions' @@ -16,6 +16,7 @@ import { getStatusbarHeight } from '../../../helpers/statusBar' import tabBar from '../app/tabBar' import { addCurrentPage } from './getCurrentPages' import { getBaseSystemInfo } from '../../api/base/getBaseSystemInfo' +import { preloadWebviews, PreloadWebviewObject } from './preLoad' interface RegisterPageOptions { url: string @@ -39,7 +40,29 @@ export function registerPage({ if (webview) { initEntry() } - // TODO preloadWebview + + if (preloadWebviews[url]) { + webview = preloadWebviews[url] + const _webview = webview as PreloadWebviewObject + if (_webview.__page__) { + // 该预载页面已处于显示状态,不再使用该预加载页面,直接新开 + if (getCurrentPages().find((page) => page === _webview.__page__)) { + if (process.env.NODE_ENV !== 'production') { + console.log( + `[uni-app] preloadWebview(${path},${_webview.id}) already in use` + ) + } + webview = undefined + } else { + // TODO eventChannel + addCurrentPage(_webview.__page__) + if (process.env.NODE_ENV !== 'production') { + console.log(`[uni-app] reuse preloadWebview(${path},${_webview.id})`) + } + return _webview + } + } + } const routeOptions = initRouteOptions(path, openType) @@ -82,7 +105,12 @@ export function registerPage({ initPageOptions(routeOptions) ) } else { - vm && addCurrentPage(vm) + initPageVm(vm!, pageInstance) + addCurrentPage(vm!) + + if ((webview as any).__preload__) { + ;(webview as any).__page__ = vm + } } return webview } -- GitLab