From cf17189f68f529fcc0844ad71601da2232951786 Mon Sep 17 00:00:00 2001 From: fxy060608 Date: Fri, 2 Jul 2021 14:14:20 +0800 Subject: [PATCH] wip(app): uni-app-plus --- packages/shims-uni-app.d.ts | 6 - packages/shims-vue-runtime.d.ts | 3 + packages/uni-app-plus/build.json | 10 +- .../uni-app-plus/dist/uni-app-service.es.js | 2217 +++++++++-------- .../uni-app-plus/dist/uni-app-view.umd.js | 21 +- .../uni-app-plus/src/service/api/index.ts | 2 + .../src/service/api/plugin/registerRuntime.ts | 21 + .../src/service/api/plugin/vuePlugin.ts | 1 + .../src/service/framework/app/index.ts | 21 + .../service/framework/app/initGlobalEvent.ts | 3 + .../src/service/framework/page/define.ts | 24 +- .../service/framework/page/getCurrentPages.ts | 21 + .../src/service/framework/page/index.ts | 6 +- .../src/service/framework/page/register.ts | 17 +- .../service/framework/page/routeOptions.ts | 2 +- .../src/service/framework/page/setup.ts | 26 +- .../src/service/framework/plugin/index.ts | 22 +- .../src/service/framework/runtime.ts | 16 + packages/uni-app-plus/src/service/index.ts | 8 +- packages/uni-app-vite/dist/plugin.js | 5 +- packages/uni-app-vite/dist/plugins/mainJs.js | 7 +- packages/uni-app-vite/src/plugin.ts | 8 +- packages/uni-app-vite/src/plugins/mainJs.ts | 8 +- packages/uni-app-vue/build.json | 4 + .../uni-app-vue/dist/service.runtime.esm.js | 129 +- packages/uni-app-vue/src/service/index.ts | 3 +- .../src/json/app/pages/uniConfig.ts | 4 +- packages/uni-core/src/helpers/bridge.ts | 19 +- .../plugin/page.ts => helpers/hook.ts} | 44 +- packages/uni-core/src/helpers/index.ts | 1 + packages/uni-core/src/helpers/page.ts | 57 + packages/uni-core/src/service/index.ts | 5 +- packages/uni-core/src/service/init/index.ts | 10 + .../src/service/{plugin => init}/on.ts | 3 +- .../src/service/{plugin => init}/subscribe.ts | 3 +- packages/uni-core/src/service/plugin/index.ts | 8 +- packages/uni-core/src/view/index.ts | 6 +- packages/uni-core/src/view/init/index.ts | 14 + .../src/view/{plugin => init}/longPress.ts | 0 .../uni-core/src/view/{plugin => init}/rem.ts | 0 packages/uni-core/src/view/plugin/index.ts | 13 +- packages/uni-h5/dist/uni-h5.cjs.js | 137 +- packages/uni-h5/dist/uni-h5.es.js | 303 +-- packages/uni-h5/src/framework/plugin/index.ts | 6 +- packages/uni-h5/src/framework/setup/app.ts | 3 + packages/uni-h5/src/framework/setup/page.ts | 36 +- .../src/service/api/media/preview-image.js | 24 - packages/uni-shared/dist/uni-shared.cjs.js | 2 +- packages/uni-shared/dist/uni-shared.es.js | 2 +- packages/uni-shared/src/url.ts | 2 +- 50 files changed, 1829 insertions(+), 1484 deletions(-) create mode 100644 packages/uni-app-plus/src/service/api/plugin/registerRuntime.ts create mode 100644 packages/uni-app-plus/src/service/api/plugin/vuePlugin.ts create mode 100644 packages/uni-app-plus/src/service/framework/page/getCurrentPages.ts create mode 100644 packages/uni-app-plus/src/service/framework/runtime.ts rename packages/uni-core/src/{service/plugin/page.ts => helpers/hook.ts} (63%) create mode 100644 packages/uni-core/src/service/init/index.ts rename packages/uni-core/src/service/{plugin => init}/on.ts (88%) rename packages/uni-core/src/service/{plugin => init}/subscribe.ts (80%) create mode 100644 packages/uni-core/src/view/init/index.ts rename packages/uni-core/src/view/{plugin => init}/longPress.ts (100%) rename packages/uni-core/src/view/{plugin => init}/rem.ts (100%) delete mode 100644 packages/uni-h5/src/service/api/media/preview-image.js diff --git a/packages/shims-uni-app.d.ts b/packages/shims-uni-app.d.ts index 537056b7db..4d659803b7 100644 --- a/packages/shims-uni-app.d.ts +++ b/packages/shims-uni-app.d.ts @@ -303,12 +303,6 @@ declare namespace UniApp { * @param callback */ unsubscribe(event: string, callback?: Function): void - /** - * 执行 Service 层 API 回调 - * @param callbackId - * @param args - */ - invokeCallbackHandler(callbackId: number, args: unknown): void /** * 向 View 层发送事件 * @param event diff --git a/packages/shims-vue-runtime.d.ts b/packages/shims-vue-runtime.d.ts index b649aadb8c..0389562dd6 100644 --- a/packages/shims-vue-runtime.d.ts +++ b/packages/shims-vue-runtime.d.ts @@ -2,6 +2,9 @@ import { UniLifecycleHooks } from '@dcloudio/uni-vue/src/apiLifecycle' import { ComponentCustomProperties, ComponentInternalInstance } from 'vue' declare module '@vue/runtime-core' { interface ComponentCustomProperties { + $scope: { + $getAppWebview: () => PlusWebviewWebviewObject + } $page: Page.PageInstance['$page'] __isTabBar: boolean } diff --git a/packages/uni-app-plus/build.json b/packages/uni-app-plus/build.json index 1cce5c7e85..7cd94b660d 100644 --- a/packages/uni-app-plus/build.json +++ b/packages/uni-app-plus/build.json @@ -5,10 +5,10 @@ "output": { "name": "serviceContext", "format": "iife", - "banner": "export function createServiceContext(weex, plus,instanceContext){\nconst jsRuntime = {};\nconst setTimeout = instanceContext.setTimeout;\nconst clearTimeout = instanceContext.clearTimeout;\nconst setInterval = instanceContext.setInterval;\nconst clearInterval = instanceContext.clearInterval;\nconst __uniConfig = instanceContext.__uniConfig;\nconst __uniRoutes = instanceContext.__uniRoutes;\n", + "banner": "export function createServiceContext(Vue,weex, plus,instanceContext){\nconst setTimeout = instanceContext.setTimeout;\nconst clearTimeout = instanceContext.clearTimeout;\nconst setInterval = instanceContext.setInterval;\nconst clearInterval = instanceContext.clearInterval;\nconst __uniConfig = instanceContext.__uniConfig;\nconst __uniRoutes = instanceContext.__uniRoutes;\n", "footer": "const uni = serviceContext.uni;\nconst getApp = serviceContext.getApp;\nconst getCurrentPages = serviceContext.getCurrentPages;\nconst UniServiceJSBridge = serviceContext.UniServiceJSBridge;\nreturn serviceContext;\n}", "globals": { - "vue": "jsRuntime" + "vue": "Vue" } }, "replacements": { @@ -22,7 +22,5 @@ "__UNI_FEATURE_I18N_ZH_HANS__": "true", "__UNI_FEATURE_I18N_ZH_HANT__": "true" }, - "external": [ - "vue" - ] -} \ No newline at end of file + "external": ["vue"] +} diff --git a/packages/uni-app-plus/dist/uni-app-service.es.js b/packages/uni-app-plus/dist/uni-app-service.es.js index 3be0424414..9d0e445297 100644 --- a/packages/uni-app-plus/dist/uni-app-service.es.js +++ b/packages/uni-app-plus/dist/uni-app-service.es.js @@ -1,5 +1,4 @@ -export function createServiceContext(weex, plus,instanceContext){ -const jsRuntime = {}; +export function createServiceContext(Vue,weex, plus,instanceContext){ const setTimeout = instanceContext.setTimeout; const clearTimeout = instanceContext.clearTimeout; const setInterval = instanceContext.setInterval; @@ -641,7 +640,7 @@ var serviceContext = (function (vue) { const [path, querystring] = url.split('?', 2); return { path, - query: parseQuery(querystring), + query: parseQuery(querystring || ''), }; } @@ -1375,10 +1374,23 @@ var serviceContext = (function (vue) { }, }; + // TODO 等待 vue3 的兼容模式自带emitter function initBridge(subscribeNamespace) { // TODO vue3 compatibility builds const emitter = new E(); - return extend(emitter, { + return { + on(event, callback) { + return emitter.on(event, callback); + }, + once(event, callback) { + return emitter.once(event, callback); + }, + off(event, callback) { + return emitter.off(event, callback); + }, + emit(event, ...args) { + return emitter.emit(event, ...args); + }, subscribe(event, callback, once = false) { emitter[once ? 'once' : 'on'](`${subscribeNamespace}.${event}`, callback); }, @@ -1391,7 +1403,7 @@ var serviceContext = (function (vue) { } emitter.emit(`${subscribeNamespace}.${event}`, args, pageId); }, - }); + }; } function hasRpx(str) { @@ -1419,6 +1431,28 @@ var serviceContext = (function (vue) { }); } + function getPageById(id) { + return getCurrentPages().find((page) => page.$page.id === id); + } + function getPageVmById(id) { + const page = getPageById(id); + if (page) { + return page.$vm; + } + } + function getCurrentPage() { + const pages = getCurrentPages(); + const len = pages.length; + if (len) { + return pages[len - 1]; + } + } + function getCurrentPageVm() { + const page = getCurrentPage(); + if (page) { + return page.$vm; + } + } const PAGE_META_KEYS = ['navigationBar', 'pullToRefresh']; function initGlobalStyle() { return JSON.parse(JSON.stringify(__uniConfig.globalStyle || {})); @@ -1442,6 +1476,39 @@ var serviceContext = (function (vue) { pullToRefresh.range = rpx2px(pullToRefresh.range); } return pullToRefresh; + } + function initPageInternalInstance(url, pageQuery, meta) { + const { id, route } = meta; + return { + id: id, + path: '/' + route, + route: route, + fullPath: url, + options: pageQuery, + meta, + }; + } + + function invokeHook(vm, name, args) { + if (isString(vm)) { + args = name; + name = vm; + vm = getCurrentPageVm(); + } + else if (typeof vm === 'number') { + const page = getCurrentPages().find((page) => page.$page.id === vm); + if (page) { + vm = page.$vm; + } + else { + vm = getCurrentPageVm(); + } + } + if (!vm) { + return; + } + const hooks = vm.$[name]; + return hooks && invokeArrayFns(hooks, args); } function normalizeRoute(toRoute) { @@ -1493,6 +1560,46 @@ var serviceContext = (function (vue) { }, }); + function initOn() { + UniServiceJSBridge.on('onAppEnterForeground', onAppEnterForeground); + UniServiceJSBridge.on('onAppEnterBackground', onAppEnterBackground); + } + function onAppEnterForeground() { + const page = getCurrentPage(); + const showOptions = { + path: '', + query: {}, + }; + if (page) { + showOptions.path = page.$page.route; + showOptions.query = page.$page.options; + } + invokeHook(getApp(), 'onShow', showOptions); + invokeHook(page, 'onShow'); + } + function onAppEnterBackground() { + invokeHook(getApp(), 'onHide'); + invokeHook(getCurrentPage(), 'onHide'); + } + + const SUBSCRIBE_LIFECYCLE_HOOKS = ['onPageScroll', 'onReachBottom']; + function initSubscribe() { + SUBSCRIBE_LIFECYCLE_HOOKS.forEach((name) => UniServiceJSBridge.subscribe(name, createPageEvent(name))); + } + function createPageEvent(name) { + return (args, pageId) => { + const vm = getPageVmById(pageId); + if (vm) { + invokeHook(vm, name, args); + } + }; + } + + function initService() { + initOn(); + initSubscribe(); + } + function querySelector(vm, selector) { const el = vm.$el.querySelector(selector); return el && el.__vue__; @@ -1536,88 +1643,7 @@ var serviceContext = (function (vue) { } } - function getPageById(id) { - return getCurrentPages().find((page) => page.$page.id === id); - } - function getPageVmById(id) { - const page = getPageById(id); - if (page) { - return page.$vm; - } - } - function getCurrentPage() { - const pages = getCurrentPages(); - const len = pages.length; - if (len) { - return pages[len - 1]; - } - } - function getCurrentPageVm() { - const page = getCurrentPage(); - if (page) { - return page.$vm; - } - } - function invokeHook(vm, name, args) { - if (isString(vm)) { - args = name; - name = vm; - vm = getCurrentPageVm(); - } - else if (typeof vm === 'number') { - const page = getCurrentPages().find((page) => page.$page.id === vm); - if (page) { - vm = page.$vm; - } - else { - vm = getCurrentPageVm(); - } - } - if (!vm) { - return; - } - const hooks = vm.$[name]; - return hooks && invokeArrayFns(hooks, args); - } - - function initOn() { - UniServiceJSBridge.on('onAppEnterForeground', onAppEnterForeground); - UniServiceJSBridge.on('onAppEnterBackground', onAppEnterBackground); - } - function onAppEnterForeground() { - const page = getCurrentPage(); - const showOptions = { - path: '', - query: {}, - }; - if (page) { - showOptions.path = page.$page.route; - showOptions.query = page.$page.options; - } - invokeHook(getApp(), 'onShow', showOptions); - invokeHook(page, 'onShow'); - } - function onAppEnterBackground() { - invokeHook(getApp(), 'onHide'); - invokeHook(getCurrentPage(), 'onHide'); - } - - const SUBSCRIBE_LIFECYCLE_HOOKS = ['onPageScroll', 'onReachBottom']; - function initSubscribe() { - SUBSCRIBE_LIFECYCLE_HOOKS.forEach((name) => UniServiceJSBridge.subscribe(name, createPageEvent(name))); - } - function createPageEvent(name) { - return (args, pageId) => { - const vm = getPageVmById(pageId); - if (vm) { - invokeHook(vm, name, args); - } - }; - } - - function initService(app) { - initOn(); - initSubscribe(); + function initServicePlugin(app) { initAppConfig(app._context.config); } @@ -5088,6 +5114,11 @@ var serviceContext = (function (vue) { return univerifyStyle; } + const registerRuntime = defineSyncApi('registerRuntime', (runtime) => { + // @ts-expect-error + extend(jsRuntime, runtime); + }); + // 0:图文,1:纯文字,2:纯图片,3:音乐,4:视频,5:小程序 const TYPES = { 0: { @@ -5203,399 +5234,385 @@ var serviceContext = (function (vue) { }, errorCallback); }, RequestPaymentProtocol); - const EventType = { - load: 'load', - close: 'close', - error: 'error', - adClicked: 'adClicked', - }; - class AdEventHandler { - constructor() { - this._callbacks = {}; + function applyOptions(options, instance, publicThis) { + Object.keys(options).forEach((name) => { + if (name.indexOf('on') === 0) { + const hook = options[name]; + if (isFunction(hook)) { + vue.injectHook(name, hook.bind(publicThis), instance); + } + } + }); + } + + function set(target, key, val) { + return (target[key] = val); + } + + function errorHandler(err, instance, info) { + if (!instance) { + throw err; } - onLoad(callback) { - this._addEventListener(EventType.load, callback); + const app = getApp(); + if (!app || !app.$vm) { + throw err; } - onClose(callback) { - this._addEventListener(EventType.close, callback); + { + invokeHook(app.$vm, 'onError', err); } - onError(callback) { - this._addEventListener(EventType.error, callback); + } + + function initApp(app) { + const appConfig = app._context.config; + if (isFunction(app._component.onError)) { + appConfig.errorHandler = errorHandler; } - offLoad(callback) { - this._removeEventListener(EventType.load, callback); + const globalProperties = appConfig.globalProperties; + { + globalProperties.$set = set; + globalProperties.$applyOptions = applyOptions; } - offClose(callback) { - this._removeEventListener(EventType.close, callback); + } + + let isInitEntryPage = false; + function initEntry() { + if (isInitEntryPage) { + return; } - offError(callback) { - this._removeEventListener(EventType.error, callback); + isInitEntryPage = true; + let entryPagePath; + let entryPageQuery; + const weexPlus = weex.requireModule('plus'); + if (weexPlus.getRedirectInfo) { + const info = weexPlus.getRedirectInfo() || {}; + entryPagePath = info.path; + entryPageQuery = info.query ? '?' + info.query : ''; } - _addEventListener(type, callback) { - if (typeof callback !== 'function') { + else { + const argsJsonStr = plus.runtime.arguments; + if (!argsJsonStr) { return; } - this._callbacks[type].push(callback); + try { + const args = JSON.parse(argsJsonStr); + entryPagePath = args.path || args.pathName; + entryPageQuery = args.query ? '?' + args.query : ''; + } + catch (e) { } } - _removeEventListener(type, callback) { - const arrayFunction = this._callbacks[type]; - const index = arrayFunction.indexOf(callback); - if (index > -1) { - arrayFunction.splice(index, 1); + if (!entryPagePath || entryPagePath === __uniConfig.entryPagePath) { + if (entryPageQuery) { + __uniConfig.entryPageQuery = entryPageQuery; } + return; } - _dispatchEvent(name, data) { - this._callbacks[name].forEach((callback) => { - callback(data || {}); - }); + const entryRoute = '/' + entryPagePath; + const routeOptions = getRouteOptions(entryRoute); + if (!routeOptions) { + return; } - } - class AdBase extends AdEventHandler { - constructor(adInstance, options) { - super(); - this._isLoaded = false; - this._isLoading = false; - this._preload = true; - this._loadPromiseResolve = null; - this._loadPromiseReject = null; - this._showPromiseResolve = null; - this._showPromiseReject = null; - this._preload = options.preload !== undefined ? options.preload : false; - const ad = (this._adInstance = adInstance); - ad.onLoad(() => { - this._isLoaded = true; - this._isLoading = false; - if (this._loadPromiseResolve != null) { - this._loadPromiseResolve(); - this._loadPromiseResolve = null; - } - if (this._showPromiseResolve != null) { - this._showPromiseResolve(); - this._showPromiseResolve = null; - this._showAd(); - } - this._dispatchEvent(EventType.load, {}); - }); - ad.onClose((e) => { - this._isLoaded = false; - this._isLoading = false; - this._dispatchEvent(EventType.close, e); - if (this._preload === true) { - this._loadAd(); - } - }); - ad.onError((e) => { - this._isLoading = false; - const data = { - code: e.code, - errMsg: e.message, - }; - this._dispatchEvent(EventType.error, data); - const error = new Error(JSON.stringify(data)); - if (this._loadPromiseReject != null) { - this._loadPromiseReject(error); - this._loadPromiseReject = null; - } - if (this._showPromiseReject != null) { - this._showPromiseReject(error); - this._showPromiseReject = null; - } - }); - ad.onAdClicked && - ad.onAdClicked(() => { - this._dispatchEvent(EventType.adClicked, {}); - }); + if (!routeOptions.meta.isTabBar) { + __uniConfig.realEntryPagePath = + __uniConfig.realEntryPagePath || __uniConfig.entryPagePath; } - getProvider() { - return this._adInstance.getProvider(); + __uniConfig.entryPagePath = entryPagePath; + __uniConfig.entryPageQuery = entryPageQuery; + } + + const isIOS = plus.os.name === 'iOS'; + let config; + /** + * tabbar显示状态 + */ + let visible = true; + let tabBar; + /** + * 设置角标 + * @param {string} type + * @param {number} index + * @param {string} text + */ + function setTabBarBadge(type, index, text) { + if (!tabBar) { + return; } - load() { - return new Promise((resolve, reject) => { - this._loadPromiseResolve = resolve; - this._loadPromiseReject = reject; - if (this._isLoading) { - return; - } - if (this._isLoaded) { - resolve(''); - } - else { - this._loadAd(); - } + if (type === 'none') { + tabBar.hideTabBarRedDot({ + index, + }); + tabBar.removeTabBarBadge({ + index, }); } - show() { - return new Promise((resolve, reject) => { - this._showPromiseResolve = resolve; - this._showPromiseReject = reject; - if (this._isLoading) { - return; - } - if (this._isLoaded) { - this._showAd(); - resolve(''); - } - else { - this._loadAd(); - } + else if (type === 'text') { + tabBar.setTabBarBadge({ + index, + text, }); } - destroy() { - this._adInstance.destroy(); + else if (type === 'redDot') { + tabBar.showTabBarRedDot({ + index, + }); } - _loadAd() { - this._isLoaded = false; - this._isLoading = true; - this._adInstance.load(); + } + /** + * 动态设置 tabBar 某一项的内容 + */ + function setTabBarItem(index, text, iconPath, selectedIconPath) { + const item = { + index, + }; + if (text !== undefined) { + item.text = text; } - _showAd() { - this._adInstance.show(); + if (iconPath) { + item.iconPath = getRealPath(iconPath); } - } - - class RewardedVideoAd extends AdBase { - constructor(options) { - super(plus.ad.createRewardedVideoAd(options), options); - this._loadAd(); + if (selectedIconPath) { + item.selectedIconPath = getRealPath(selectedIconPath); } + tabBar && tabBar.setTabBarItem(item); } - const createRewardedVideoAd = (defineSyncApi(API_CREATE_REWARDED_VIDEO_AD, (options) => { - return new RewardedVideoAd(options); - }, CreateRewardedVideoAdProtocol, CreateRewardedVideoAdOptions)); - - class FullScreenVideoAd extends AdBase { - constructor(options) { - super(plus.ad.createFullScreenVideoAd(options), options); - } + /** + * 动态设置 tabBar 的整体样式 + * @param {Object} style 样式 + */ + function setTabBarStyle(style) { + tabBar && tabBar.setTabBarStyle(style); } - const createFullScreenVideoAd = (defineSyncApi(API_CREATE_FULL_SCREEN_VIDEO_AD, (options) => { - return new FullScreenVideoAd(options); - }, CreateFullScreenVideoAdProtocol, CreateFullScreenVideoAdOptions)); - - class InterstitialAd extends AdBase { - constructor(options) { - super(plus.ad.createInterstitialAd(options), options); - this._loadAd(); - } + /** + * 隐藏 tabBar + * @param {boolean} animation 是否需要动画效果 + */ + function hideTabBar(animation) { + visible = false; + tabBar && + tabBar.hideTabBar({ + animation, + }); } - const createInterstitialAd = (defineSyncApi(API_CREATE_INTERSTITIAL_AD, (options) => { - return new InterstitialAd(options); - }, CreateInterstitialAdProtocol, CreateInterstitialAdOptions)); - - const sdkCache = {}; - const sdkQueue = {}; - function initSDK(options) { - const provider = options.provider; - if (!sdkCache[provider]) { - sdkCache[provider] = {}; - } - if (typeof sdkCache[provider].plugin === 'object') { - options.success(sdkCache[provider].plugin); - return; - } - if (!sdkQueue[provider]) { - sdkQueue[provider] = []; - } - sdkQueue[provider].push(options); - if (sdkCache[provider].status === true) { - options.__plugin = sdkCache[provider].plugin; - return; - } - sdkCache[provider].status = true; - const plugin = requireNativePlugin(provider); - if (!plugin || !plugin.initSDK) { - sdkQueue[provider].forEach((item) => { - item.fail({ - code: -1, - message: 'provider [' + provider + '] invalid', - }); + /** + * 显示 tabBar + * @param {boolean} animation 是否需要动画效果 + */ + function showTabBar(animation) { + visible = true; + tabBar && + tabBar.showTabBar({ + animation, }); - sdkQueue[provider].length = 0; - sdkCache[provider].status = false; - return; - } - // TODO - sdkCache[provider].plugin = plugin; - options.__plugin = plugin; - plugin.initSDK((res) => { - const isSuccess = res.code === 1 || res.code === '1'; - if (isSuccess) { - sdkCache[provider].plugin = plugin; - } - else { - sdkCache[provider].status = false; - } - sdkQueue[provider].forEach((item) => { - if (isSuccess) { - item.success(item.__plugin); - } - else { - item.fail(res); - } - }); - sdkQueue[provider].length = 0; - }); } - class InteractiveAd extends AdEventHandler { - constructor(options) { - super(); - this._adpid = ''; - this._provider = ''; - this._userData = null; - this._isLoaded = false; - this._isLoading = false; - this._loadPromiseResolve = null; - this._loadPromiseReject = null; - this._showPromiseResolve = null; - this._showPromiseReject = null; - this._adInstance = null; - this._adError = ''; - this._adpid = options.adpid; - this._provider = options.provider; - this._userData = options.userData; - setTimeout(() => { - this._init(); + const maskClickCallback = []; + var tabBar$1 = { + id: '0', + init(options, clickCallback) { + if (options && options.list.length) { + config = options; + } + try { + tabBar = weex.requireModule('uni-tabview'); + } + catch (error) { + console.log(`uni.requireNativePlugin("uni-tabview") error ${error}`); + } + tabBar.onMaskClick(() => { + maskClickCallback.forEach((callback) => { + callback(); + }); }); - } - _init() { - this._adError = ''; - initSDK({ - provider: this._provider, - success: (res) => { - this._adInstance = res; - if (this._userData) { - this.bindUserData(this._userData); - } - this._loadAd(); - }, - fail: (err) => { - this._adError = err; - if (this._loadPromiseReject != null) { - this._loadPromiseReject(this._createError(err)); - this._loadPromiseReject = null; + tabBar && + tabBar.onClick(({ index }) => { + clickCallback(config.list[index], index); + }); + tabBar && + tabBar.onMidButtonClick(() => { + // publish('onTabBarMidButtonTap', {}) + }); + }, + indexOf(page) { + const itemLength = config && config.list && config.list.length; + if (itemLength) { + for (let i = 0; i < itemLength; i++) { + if (config.list[i].pagePath === page || + config.list[i].pagePath === `${page}.html`) { + return i; } - this._dispatchEvent(EventType.error, err); - }, - }); - } - getProvider() { - return this._provider; - } - load() { - return new Promise((resolve, reject) => { - this._loadPromiseResolve = resolve; - this._loadPromiseReject = reject; - if (this._isLoading) { - return; - } - if (this._adError) { - this._init(); - return; - } - if (this._isLoaded) { - resolve(''); - } - else { - this._loadAd(); } + } + return -1; + }, + switchTab(page) { + const index = this.indexOf(page); + if (index >= 0) { + tabBar && + tabBar.switchSelect({ + index, + }); + return true; + } + return false; + }, + setTabBarBadge, + setTabBarItem, + setTabBarStyle, + hideTabBar, + showTabBar, + append(webview) { + tabBar && + tabBar.append({ + id: webview.id, + }, ({ code }) => { + if (code !== 0) { + setTimeout(() => { + this.append(webview); + }, 20); + } + }); + }, + get visible() { + return visible; + }, + get height() { + return ((config && config.height ? parseFloat(config.height) : TABBAR_HEIGHT) + + plus.navigator.getSafeAreaInsets().deviceBottom); + }, + // tabBar是否遮挡内容区域 + get cover() { + const array = ['extralight', 'light', 'dark']; + return isIOS && array.indexOf(config.blurEffect) >= 0; + }, + setStyle({ mask }) { + tabBar.setMask({ + color: mask, }); + }, + addEventListener(_name, callback) { + maskClickCallback.push(callback); + }, + removeEventListener(_name, callback) { + const callbackIndex = maskClickCallback.indexOf(callback); + maskClickCallback.splice(callbackIndex, 1); + }, + }; + + function initTabBar() { + const { tabBar } = __uniConfig; + const len = tabBar && tabBar.list && tabBar.list.length; + if (!len) { + return; } - show() { - return new Promise((resolve, reject) => { - this._showPromiseResolve = resolve; - this._showPromiseReject = reject; - if (this._isLoading) { - return; - } - if (this._adError) { - this._init(); - return; - } - if (this._isLoaded) { - this._showAd(); - resolve(''); - } - else { - this._loadAd(); - } + const { entryPagePath } = __uniConfig; + tabBar.selectedIndex = 0; + const selected = tabBar.list.findIndex((page) => page.pagePath === entryPagePath); + tabBar$1.init(tabBar, (item, index) => { + uni.switchTab({ + url: '/' + item.pagePath, + openType: 'switchTab', + from: 'tabBar', + success() { + invokeHook('onTabItemTap', { + index, + text: item.text, + pagePath: item.pagePath, + }); + }, }); + }); + if (selected !== -1) { + // 取当前 tab 索引值 + tabBar.selectedIndex = selected; + selected !== 0 && tabBar$1.switchTab(entryPagePath); } - reportExposure() { - if (this._adInstance !== null) { - this._adInstance.reportExposure(); - } - } - bindUserData(data) { - if (this._adInstance !== null) { - this._adInstance.bindUserData(data); - } - } - destroy() { - if (this._adInstance !== null && this._adInstance.destroy) { - this._adInstance.destroy({ - adpid: this._adpid, - }); - } + } + + function backbuttonListener() { + uni.navigateBack({ + from: 'backbutton', + }); + } + + function initGlobalEvent() { + const plusGlobalEvent = plus.globalEvent; + const weexGlobalEvent = weex.requireModule('globalEvent'); + const emit = UniServiceJSBridge.emit; + if (weex.config.preload) { + plus.key.addEventListener('backbutton', backbuttonListener); } - _loadAd() { - if (this._adInstance !== null) { - if (this._isLoading === true) { - return; - } - this._isLoading = true; - this._adInstance.loadData({ - adpid: this._adpid, - }, (res) => { - this._isLoaded = true; - this._isLoading = false; - if (this._loadPromiseResolve != null) { - this._loadPromiseResolve(); - this._loadPromiseResolve = null; - } - if (this._showPromiseResolve != null) { - this._showPromiseResolve(); - this._showPromiseResolve = null; - this._showAd(); - } - this._dispatchEvent(EventType.load, res); - }, (err) => { - this._isLoading = false; - if (this._showPromiseReject != null) { - this._showPromiseReject(this._createError(err)); - this._showPromiseReject = null; - } - this._dispatchEvent(EventType.error, err); - }); - } + else { + plusGlobalEvent.addEventListener('splashclosed', () => { + plus.key.addEventListener('backbutton', backbuttonListener); + }); } - _showAd() { - if (this._adInstance !== null && this._isLoaded === true) { - this._adInstance.show({ - adpid: this._adpid, - }, () => { - this._isLoaded = false; - }, (err) => { - this._isLoaded = false; - if (this._showPromiseReject != null) { - this._showPromiseReject(this._createError(err)); - this._showPromiseReject = null; - } - this._dispatchEvent(EventType.error, err); - }); - } + plusGlobalEvent.addEventListener('pause', () => { + emit('onAppEnterBackground'); + }); + plusGlobalEvent.addEventListener('resume', () => { + emit('onAppEnterForeground'); + }); + weexGlobalEvent.addEventListener('uistylechange', function (event) { + const args = { + theme: event.uistyle, + }; + emit('onThemeChange', args); + }); + plusGlobalEvent.addEventListener('plusMessage', subscribePlusMessage); + // nvue webview post message + plusGlobalEvent.addEventListener('WebviewPostMessage', subscribePlusMessage); + } + function subscribePlusMessage({ data, }) { + if ((process.env.NODE_ENV !== 'production')) { + console.log('plusMessage:' + JSON.stringify(data)); } - _createError(err) { - return new Error(JSON.stringify(err)); + if (data && data.type) { + UniServiceJSBridge.subscribeHandler('plusMessage.' + data.type, data.args); } } - const createInteractiveAd = (defineSyncApi(API_CREATE_INTERACTIVE_AD, (options) => { - return new InteractiveAd(options); - }, CreateInteractiveAdProtocol, CreateInteractiveAdOptions)); + function onPlusMessage(type, callback, once = false) { + UniServiceJSBridge.subscribe('plusMessage.' + type, callback, once); + } - const downgrade = plus.os.name === 'Android' && parseInt(plus.os.version) < 6; - const ANI_SHOW = downgrade ? 'slide-in-right' : 'pop-in'; - const ANI_DURATION = 300; - const VIEW_WEBVIEW_PATH = '_www/__uniappview.html'; + function initAppLaunch(appVm) { + const args = { + path: __uniConfig.entryPagePath, + query: {}, + scene: 1001, + }; + invokeHook(appVm, 'onLaunch', args); + invokeHook(appVm, 'onShow', args); + } + + // 统一处理路径 + function getPath(path) { + path = path.replace(/\/$/, ''); + return path.indexOf('_') === 0 + ? plus.io.convertLocalFileSystemURL(path) + : path; + } + function clearTempFile() { + const basePath = getPath(TEMP_PATH_BASE); + const tempPath = getPath(TEMP_PATH); + // 获取父目录 + const dirParts = tempPath.split('/'); + dirParts.pop(); + const dirPath = dirParts.join('/'); + plus.io.resolveLocalFileSystemURL(plus.io.convertAbsoluteFileSystem(dirPath), (entry) => { + const reader = entry.createReader(); + reader.readEntries(function (entry) { + // plus.d.ts 类型不对 + const entries = entry; + if (entries && entries.length) { + entries.forEach(function (entry) { + if (entry.isDirectory && + entry.fullPath.indexOf(basePath) === 0 && + entry.fullPath.indexOf(tempPath) !== 0) { + entry.removeRecursively(); + } + }); + } + }); + }); + } const ON_WEBVIEW_READY = 'onWebviewReady'; @@ -5827,6 +5844,11 @@ var serviceContext = (function (vue) { } } + const downgrade = plus.os.name === 'Android' && parseInt(plus.os.version) < 6; + const ANI_SHOW = downgrade ? 'slide-in-right' : 'pop-in'; + const ANI_DURATION = 300; + const VIEW_WEBVIEW_PATH = '_www/__uniappview.html'; + let preloadWebview; function setPreloadWebview(webview) { preloadWebview = webview; @@ -5856,719 +5878,771 @@ var serviceContext = (function (vue) { UniServiceJSBridge.once(ON_WEBVIEW_READY + '.' + pageId, callback); } - let pendingNavigator = false; - function setPendingNavigator(path, callback, msg) { - pendingNavigator = { - path, - nvue: getRouteMeta(path).isNVue, - callback, - }; - if ((process.env.NODE_ENV !== 'production')) { - console.log(`nextNavigator:${path} ${msg}`); - } - } - function navigate(path, callback, isAppLaunch) { - if (!isAppLaunch && pendingNavigator) { - return console.error(`Waiting to navigate to: ${pendingNavigator.path}, do not operate continuously: ${path}.`); - } - if (__uniConfig.renderer === 'native') { - // 纯原生无需wait逻辑 - // 如果是首页还未初始化,需要等一等,其他无需等待 - if (getCurrentPages().length === 0) { - return setPendingNavigator(path, callback, 'waitForReady'); + let isLaunchWebviewReady = false; // 目前首页双向确定 ready,可能会导致触发两次 onWebviewReady(主要是 Android) + function subscribeWebviewReady(_data, pageId) { + const isLaunchWebview = pageId === '1'; + if (isLaunchWebview && isLaunchWebviewReady) { + if ((process.env.NODE_ENV !== 'production')) { + console.log('[uni-app] onLaunchWebviewReady.prevent'); } - return callback(); + return; } - // 未创建 preloadWebview 或 preloadWebview 已被使用 - const waitPreloadWebview = !preloadWebview || (preloadWebview && preloadWebview.__uniapp_route); - // 已创建未 loaded - const waitPreloadWebviewReady = preloadWebview && !preloadWebview.loaded; - if (waitPreloadWebview || waitPreloadWebviewReady) { - setPendingNavigator(path, callback, waitPreloadWebview ? 'waitForCreate' : 'waitForReady'); + if (isLaunchWebview) { + // 首页 + isLaunchWebviewReady = true; + setPreloadWebview(plus.webview.getLaunchWebview()); } - else { - callback(); + else if (!preloadWebview) { + // preloadWebview 不存在,重新加载一下 + setPreloadWebview(plus.webview.getWebviewById(pageId)); } - if (waitPreloadWebviewReady) { - onWebviewReady(preloadWebview.id, pendingNavigate); + if (preloadWebview.id !== pageId) { + return console.error(`webviewReady[${preloadWebview.id}][${pageId}] not match`); } + preloadWebview.loaded = true; // 标记已 ready + UniServiceJSBridge.emit(ON_WEBVIEW_READY + '.' + pageId); + isLaunchWebview && onLaunchWebviewReady(); } - function pendingNavigate() { - if (!pendingNavigator) { - return; - } - const { callback } = pendingNavigator; - if ((process.env.NODE_ENV !== 'production')) { - console.log(`pendingNavigate:${pendingNavigator.path}`); + function onLaunchWebviewReady() { + const { autoclose, alwaysShowBeforeRender } = __uniConfig.splashscreen; + if (autoclose && !alwaysShowBeforeRender) { + plus.navigator.closeSplashscreen(); } - pendingNavigator = false; - return callback(); - } - function navigateFinish() { - if (__uniConfig.renderer === 'native') { - if (!pendingNavigator) { - return; - } - if (pendingNavigator.nvue) { - return pendingNavigate(); + const entryPagePath = '/' + __uniConfig.entryPagePath; + const routeOptions = getRouteOptions(entryPagePath); + if (!routeOptions.meta.isNVue) { + // 非 nvue 首页,需要主动跳转 + const args = { + url: entryPagePath + (__uniConfig.entryPageQuery || ''), + openType: 'appLaunch', + }; + if (routeOptions.meta.isTabBar) { + return uni.switchTab(args); } - return; - } - // 创建预加载 - const preloadWebview = createPreloadWebview(); - if ((process.env.NODE_ENV !== 'production')) { - console.log(`navigateFinish.preloadWebview:${preloadWebview.id}`); - } - if (!pendingNavigator) { - return; - } - if (pendingNavigator.nvue) { - return pendingNavigate(); + return uni.navigateTo(args); } - preloadWebview.loaded - ? pendingNavigator.callback() - : onWebviewReady(preloadWebview.id, pendingNavigate); } - function showWebview(webview, animationType, animationDuration, showCallback, delay) { - if (typeof delay === 'undefined') { - delay = webview.nvue ? 0 : 100; - } - if ((process.env.NODE_ENV !== 'production')) { - console.log(`[show][${Date.now()}]`, delay); + function initSubscribeHandlers() { + const { subscribe, subscribeHandler } = UniServiceJSBridge; + onPlusMessage('subscribeHandler', ({ type, data, pageId }) => { + subscribeHandler(type, data, pageId); + }); + if (__uniConfig.renderer !== 'native') { + // 非纯原生 + subscribe(ON_WEBVIEW_READY, subscribeWebviewReady); } - const execShowCallback = function () { - if (execShowCallback._called) { - if ((process.env.NODE_ENV !== 'production')) { - console.log('execShowCallback.prevent'); - } - return; - } - execShowCallback._called = true; - showCallback && showCallback(); - navigateFinish(); - }; - execShowCallback._called = false; - setTimeout(() => { - const timer = setTimeout(() => { - if ((process.env.NODE_ENV !== 'production')) { - console.log(`[show.callback.timer][${Date.now()}]`); - } - execShowCallback(); - }, animationDuration + 150); - webview.show(animationType, animationDuration, () => { - if ((process.env.NODE_ENV !== 'production')) { - console.log(`[show.callback][${Date.now()}]`); - } - if (!execShowCallback._called) { - clearTimeout(timer); - } - execShowCallback(); - }); - }, delay); } - const BRIDGE_NODE_SYNC = 'nodeSync'; - const ACTION_TYPE_PAGE_CREATE = 1; - const ACTION_TYPE_PAGE_CREATED = 2; - const ACTION_TYPE_CREATE = 3; - const ACTION_TYPE_INSERT = 4; - const ACTION_TYPE_REMOVE = 5; - const ACTION_TYPE_SET_ATTRIBUTE = 6; - const ACTION_TYPE_REMOVE_ATTRIBUTE = 7; - const ACTION_TYPE_SET_TEXT = 8; - class UniPageNode extends UniNode { - constructor(pageId, options, setup = false) { - super(NODE_TYPE_PAGE, '#page', null); - this._id = 1; - this.updateActions = []; - this.nodeId = 0; - this.pageId = pageId; - this.pageNode = this; - this.createAction = [ACTION_TYPE_PAGE_CREATE, options]; - this.createdAction = [ACTION_TYPE_PAGE_CREATED]; - setup && this.setup(); - } - onCreate(thisNode, nodeName) { - pushCreateAction(this, thisNode.nodeId, nodeName); - return thisNode; + let appCtx; + const defaultApp = { + globalData: {}, + }; + function getApp$1({ allowDefault = false } = {}) { + if (appCtx) { + // 真实的 App 已初始化 + return appCtx; } - onInsertBefore(thisNode, newChild, index) { - pushInsertAction(this, newChild, thisNode.nodeId, index); - return newChild; + if (allowDefault) { + // 返回默认实现 + return defaultApp; } - onRemoveChild(thisNode, oldChild) { - pushRemoveAction(this, oldChild.nodeId, thisNode.nodeId); - return oldChild; + console.error('[warn]: getApp() failed. Learn more: https://uniapp.dcloud.io/collocation/frame/window?id=getapp.'); + } + function registerApp(appVm) { + if ((process.env.NODE_ENV !== 'production')) { + console.log('registerApp'); } - onSetAttribute(thisNode, qualifiedName, value) { - if (thisNode.parentNode) { - pushSetAttributeAction(this, thisNode.nodeId, qualifiedName, value); - } + appCtx = appVm; + appCtx.$vm = appVm; + extend(appCtx, defaultApp); // 拷贝默认实现 + const { $options } = appVm; + if ($options) { + appCtx.globalData = extend($options.globalData || {}, appCtx.globalData); } - onRemoveAttribute(thisNode, qualifiedName) { - if (thisNode.parentNode) { - pushRemoveAttributeAction(this, thisNode.nodeId, qualifiedName); + initService(); + initEntry(); + initTabBar(); + initGlobalEvent(); + initSubscribeHandlers(); + initAppLaunch(appVm); + // 10s后清理临时文件 + setTimeout(clearTempFile, 10000); + __uniConfig.ready = true; + } + + var __vuePlugin = { + install(app) { + initMount(app); + initApp(app); + initServicePlugin(app); + }, + }; + function initMount(app) { + const oldMount = app.mount; + app.mount = (rootContainer) => { + const instance = oldMount.call(app, rootContainer); + if (rootContainer === '#app') { + registerApp(instance); } + return instance; + }; + } + + const EventType = { + load: 'load', + close: 'close', + error: 'error', + adClicked: 'adClicked', + }; + class AdEventHandler { + constructor() { + this._callbacks = {}; } - onTextContent(thisNode, text) { - if (thisNode.parentNode) { - pushSetTextAction(this, thisNode.nodeId, text); - } + onLoad(callback) { + this._addEventListener(EventType.load, callback); } - onNodeValue(thisNode, val) { - if (thisNode.parentNode) { - pushSetTextAction(this, thisNode.nodeId, val); - } + onClose(callback) { + this._addEventListener(EventType.close, callback); } - genId() { - return this._id++; + onError(callback) { + this._addEventListener(EventType.error, callback); } - push(action) { - this.updateActions.push(action); + offLoad(callback) { + this._removeEventListener(EventType.load, callback); } - restore() { - this.push(this.createAction); - // TODO restore children - this.push(this.createdAction); + offClose(callback) { + this._removeEventListener(EventType.close, callback); } - setup() { - this.send([this.createAction]); + offError(callback) { + this._removeEventListener(EventType.error, callback); } - mounted() { - const { updateActions, createdAction } = this; - updateActions.unshift(createdAction); - this.update(); + _addEventListener(type, callback) { + if (typeof callback !== 'function') { + return; + } + this._callbacks[type].push(callback); } - update() { - const { updateActions } = this; - if (updateActions.length) { - this.send(updateActions); - updateActions.length = 0; + _removeEventListener(type, callback) { + const arrayFunction = this._callbacks[type]; + const index = arrayFunction.indexOf(callback); + if (index > -1) { + arrayFunction.splice(index, 1); } } - send(action) { - UniServiceJSBridge.publishHandler(BRIDGE_NODE_SYNC, action, this.pageId); + _dispatchEvent(name, data) { + this._callbacks[name].forEach((callback) => { + callback(data || {}); + }); } } - function pushCreateAction(pageNode, nodeId, nodeName) { - pageNode.push([ACTION_TYPE_CREATE, nodeId, nodeName]); - } - function pushInsertAction(pageNode, newChild, parentNodeId, index) { - pageNode.push([ - ACTION_TYPE_INSERT, - newChild.nodeId, - parentNodeId, - index, - newChild.toJSON({ attr: true }), - ]); - } - function pushRemoveAction(pageNode, nodeId, parentNodeId) { - pageNode.push([ACTION_TYPE_REMOVE, nodeId, parentNodeId]); - } - function pushSetAttributeAction(pageNode, nodeId, name, value) { - pageNode.push([ACTION_TYPE_SET_ATTRIBUTE, nodeId, name, value]); - } - function pushRemoveAttributeAction(pageNode, nodeId, name) { - pageNode.push([ACTION_TYPE_REMOVE_ATTRIBUTE, nodeId, name]); - } - function pushSetTextAction(pageNode, nodeId, text) { - pageNode.push([ACTION_TYPE_SET_TEXT, nodeId, text]); - } - function createPageNode(pageId, pageOptions, setup) { - return new UniPageNode(pageId, pageOptions, setup); - } - - function setupPage(component) { - if ((process.env.NODE_ENV !== 'production')) { - console.log(`setupPage`); + class AdBase extends AdEventHandler { + constructor(adInstance, options) { + super(); + this._isLoaded = false; + this._isLoading = false; + this._preload = true; + this._loadPromiseResolve = null; + this._loadPromiseReject = null; + this._showPromiseResolve = null; + this._showPromiseReject = null; + this._preload = options.preload !== undefined ? options.preload : false; + const ad = (this._adInstance = adInstance); + ad.onLoad(() => { + this._isLoaded = true; + this._isLoading = false; + if (this._loadPromiseResolve != null) { + this._loadPromiseResolve(); + this._loadPromiseResolve = null; + } + if (this._showPromiseResolve != null) { + this._showPromiseResolve(); + this._showPromiseResolve = null; + this._showAd(); + } + this._dispatchEvent(EventType.load, {}); + }); + ad.onClose((e) => { + this._isLoaded = false; + this._isLoading = false; + this._dispatchEvent(EventType.close, e); + if (this._preload === true) { + this._loadAd(); + } + }); + ad.onError((e) => { + this._isLoading = false; + const data = { + code: e.code, + errMsg: e.message, + }; + this._dispatchEvent(EventType.error, data); + const error = new Error(JSON.stringify(data)); + if (this._loadPromiseReject != null) { + this._loadPromiseReject(error); + this._loadPromiseReject = null; + } + if (this._showPromiseReject != null) { + this._showPromiseReject(error); + this._showPromiseReject = null; + } + }); + ad.onAdClicked && + ad.onAdClicked(() => { + this._dispatchEvent(EventType.adClicked, {}); + }); } - const oldSetup = component.setup; - component.setup = (props, ctx) => { - const { pagePath, pageQuery } = props; - if ((process.env.NODE_ENV !== 'production')) { - console.log(`${pagePath} setup`); - } - if (oldSetup) { - return oldSetup(pageQuery, ctx); - } - }; - return component; - } - - function applyOptions(options, instance, publicThis) { - Object.keys(options).forEach((name) => { - if (name.indexOf('on') === 0) { - const hook = options[name]; - if (isFunction(hook)) { - vue.injectHook(name, hook.bind(publicThis), instance); + getProvider() { + return this._adInstance.getProvider(); + } + load() { + return new Promise((resolve, reject) => { + this._loadPromiseResolve = resolve; + this._loadPromiseReject = reject; + if (this._isLoading) { + return; } - } - }); - } - - function set(target, key, val) { - return (target[key] = val); - } - - function errorHandler(err, instance, info) { - if (!instance) { - throw err; + if (this._isLoaded) { + resolve(''); + } + else { + this._loadAd(); + } + }); } - const app = getApp(); - if (!app || !app.$vm) { - throw err; + show() { + return new Promise((resolve, reject) => { + this._showPromiseResolve = resolve; + this._showPromiseReject = reject; + if (this._isLoading) { + return; + } + if (this._isLoaded) { + this._showAd(); + resolve(''); + } + else { + this._loadAd(); + } + }); } - { - invokeHook(app.$vm, 'onError', err); + destroy() { + this._adInstance.destroy(); } - } - - function initApp(app) { - const appConfig = app._context.config; - if (isFunction(app._component.onError)) { - appConfig.errorHandler = errorHandler; + _loadAd() { + this._isLoaded = false; + this._isLoading = true; + this._adInstance.load(); } - const globalProperties = appConfig.globalProperties; - { - globalProperties.$set = set; - globalProperties.$applyOptions = applyOptions; + _showAd() { + this._adInstance.show(); } } - let isInitEntryPage = false; - function initEntry() { - if (isInitEntryPage) { - return; + class RewardedVideoAd extends AdBase { + constructor(options) { + super(plus.ad.createRewardedVideoAd(options), options); + this._loadAd(); } - isInitEntryPage = true; - let entryPagePath; - let entryPageQuery; - const weexPlus = weex.requireModule('plus'); - if (weexPlus.getRedirectInfo) { - const info = weexPlus.getRedirectInfo() || {}; - entryPagePath = info.path; - entryPageQuery = info.query ? '?' + info.query : ''; + } + const createRewardedVideoAd = (defineSyncApi(API_CREATE_REWARDED_VIDEO_AD, (options) => { + return new RewardedVideoAd(options); + }, CreateRewardedVideoAdProtocol, CreateRewardedVideoAdOptions)); + + class FullScreenVideoAd extends AdBase { + constructor(options) { + super(plus.ad.createFullScreenVideoAd(options), options); } - else { - const argsJsonStr = plus.runtime.arguments; - if (!argsJsonStr) { - return; - } - try { - const args = JSON.parse(argsJsonStr); - entryPagePath = args.path || args.pathName; - entryPageQuery = args.query ? '?' + args.query : ''; - } - catch (e) { } + } + const createFullScreenVideoAd = (defineSyncApi(API_CREATE_FULL_SCREEN_VIDEO_AD, (options) => { + return new FullScreenVideoAd(options); + }, CreateFullScreenVideoAdProtocol, CreateFullScreenVideoAdOptions)); + + class InterstitialAd extends AdBase { + constructor(options) { + super(plus.ad.createInterstitialAd(options), options); + this._loadAd(); } - if (!entryPagePath || entryPagePath === __uniConfig.entryPagePath) { - if (entryPageQuery) { - __uniConfig.entryPageQuery = entryPageQuery; - } - return; + } + const createInterstitialAd = (defineSyncApi(API_CREATE_INTERSTITIAL_AD, (options) => { + return new InterstitialAd(options); + }, CreateInterstitialAdProtocol, CreateInterstitialAdOptions)); + + const sdkCache = {}; + const sdkQueue = {}; + function initSDK(options) { + const provider = options.provider; + if (!sdkCache[provider]) { + sdkCache[provider] = {}; } - const entryRoute = '/' + entryPagePath; - const routeOptions = getRouteOptions(entryRoute); - if (!routeOptions) { + if (typeof sdkCache[provider].plugin === 'object') { + options.success(sdkCache[provider].plugin); return; } - if (!routeOptions.meta.isTabBar) { - __uniConfig.realEntryPagePath = - __uniConfig.realEntryPagePath || __uniConfig.entryPagePath; + if (!sdkQueue[provider]) { + sdkQueue[provider] = []; } - __uniConfig.entryPagePath = entryPagePath; - __uniConfig.entryPageQuery = entryPageQuery; - } - - const isIOS = plus.os.name === 'iOS'; - let config; - /** - * tabbar显示状态 - */ - let visible = true; - let tabBar; - /** - * 设置角标 - * @param {string} type - * @param {number} index - * @param {string} text - */ - function setTabBarBadge(type, index, text) { - if (!tabBar) { + sdkQueue[provider].push(options); + if (sdkCache[provider].status === true) { + options.__plugin = sdkCache[provider].plugin; return; } - if (type === 'none') { - tabBar.hideTabBarRedDot({ - index, - }); - tabBar.removeTabBarBadge({ - index, - }); - } - else if (type === 'text') { - tabBar.setTabBarBadge({ - index, - text, + sdkCache[provider].status = true; + const plugin = requireNativePlugin(provider); + if (!plugin || !plugin.initSDK) { + sdkQueue[provider].forEach((item) => { + item.fail({ + code: -1, + message: 'provider [' + provider + '] invalid', + }); }); + sdkQueue[provider].length = 0; + sdkCache[provider].status = false; + return; } - else if (type === 'redDot') { - tabBar.showTabBarRedDot({ - index, + // TODO + sdkCache[provider].plugin = plugin; + options.__plugin = plugin; + plugin.initSDK((res) => { + const isSuccess = res.code === 1 || res.code === '1'; + if (isSuccess) { + sdkCache[provider].plugin = plugin; + } + else { + sdkCache[provider].status = false; + } + sdkQueue[provider].forEach((item) => { + if (isSuccess) { + item.success(item.__plugin); + } + else { + item.fail(res); + } }); - } + sdkQueue[provider].length = 0; + }); } - /** - * 动态设置 tabBar 某一项的内容 - */ - function setTabBarItem(index, text, iconPath, selectedIconPath) { - const item = { - index, - }; - if (text !== undefined) { - item.text = text; + class InteractiveAd extends AdEventHandler { + constructor(options) { + super(); + this._adpid = ''; + this._provider = ''; + this._userData = null; + this._isLoaded = false; + this._isLoading = false; + this._loadPromiseResolve = null; + this._loadPromiseReject = null; + this._showPromiseResolve = null; + this._showPromiseReject = null; + this._adInstance = null; + this._adError = ''; + this._adpid = options.adpid; + this._provider = options.provider; + this._userData = options.userData; + setTimeout(() => { + this._init(); + }); } - if (iconPath) { - item.iconPath = getRealPath(iconPath); + _init() { + this._adError = ''; + initSDK({ + provider: this._provider, + success: (res) => { + this._adInstance = res; + if (this._userData) { + this.bindUserData(this._userData); + } + this._loadAd(); + }, + fail: (err) => { + this._adError = err; + if (this._loadPromiseReject != null) { + this._loadPromiseReject(this._createError(err)); + this._loadPromiseReject = null; + } + this._dispatchEvent(EventType.error, err); + }, + }); } - if (selectedIconPath) { - item.selectedIconPath = getRealPath(selectedIconPath); + getProvider() { + return this._provider; } - tabBar && tabBar.setTabBarItem(item); - } - /** - * 动态设置 tabBar 的整体样式 - * @param {Object} style 样式 - */ - function setTabBarStyle(style) { - tabBar && tabBar.setTabBarStyle(style); - } - /** - * 隐藏 tabBar - * @param {boolean} animation 是否需要动画效果 - */ - function hideTabBar(animation) { - visible = false; - tabBar && - tabBar.hideTabBar({ - animation, + load() { + return new Promise((resolve, reject) => { + this._loadPromiseResolve = resolve; + this._loadPromiseReject = reject; + if (this._isLoading) { + return; + } + if (this._adError) { + this._init(); + return; + } + if (this._isLoaded) { + resolve(''); + } + else { + this._loadAd(); + } }); - } - /** - * 显示 tabBar - * @param {boolean} animation 是否需要动画效果 - */ - function showTabBar(animation) { - visible = true; - tabBar && - tabBar.showTabBar({ - animation, + } + show() { + return new Promise((resolve, reject) => { + this._showPromiseResolve = resolve; + this._showPromiseReject = reject; + if (this._isLoading) { + return; + } + if (this._adError) { + this._init(); + return; + } + if (this._isLoaded) { + this._showAd(); + resolve(''); + } + else { + this._loadAd(); + } }); - } - const maskClickCallback = []; - var tabBar$1 = { - id: '0', - init(options, clickCallback) { - if (options && options.list.length) { - config = options; - } - try { - tabBar = weex.requireModule('uni-tabview'); + } + reportExposure() { + if (this._adInstance !== null) { + this._adInstance.reportExposure(); } - catch (error) { - console.log(`uni.requireNativePlugin("uni-tabview") error ${error}`); + } + bindUserData(data) { + if (this._adInstance !== null) { + this._adInstance.bindUserData(data); } - tabBar.onMaskClick(() => { - maskClickCallback.forEach((callback) => { - callback(); - }); - }); - tabBar && - tabBar.onClick(({ index }) => { - clickCallback(config.list[index], index); - }); - tabBar && - tabBar.onMidButtonClick(() => { - // publish('onTabBarMidButtonTap', {}) + } + destroy() { + if (this._adInstance !== null && this._adInstance.destroy) { + this._adInstance.destroy({ + adpid: this._adpid, }); - }, - indexOf(page) { - const itemLength = config && config.list && config.list.length; - if (itemLength) { - for (let i = 0; i < itemLength; i++) { - if (config.list[i].pagePath === page || - config.list[i].pagePath === `${page}.html`) { - return i; - } - } } - return -1; - }, - switchTab(page) { - const index = this.indexOf(page); - if (index >= 0) { - tabBar && - tabBar.switchSelect({ - index, - }); - return true; + } + _loadAd() { + if (this._adInstance !== null) { + if (this._isLoading === true) { + return; + } + this._isLoading = true; + this._adInstance.loadData({ + adpid: this._adpid, + }, (res) => { + this._isLoaded = true; + this._isLoading = false; + if (this._loadPromiseResolve != null) { + this._loadPromiseResolve(); + this._loadPromiseResolve = null; + } + if (this._showPromiseResolve != null) { + this._showPromiseResolve(); + this._showPromiseResolve = null; + this._showAd(); + } + this._dispatchEvent(EventType.load, res); + }, (err) => { + this._isLoading = false; + if (this._showPromiseReject != null) { + this._showPromiseReject(this._createError(err)); + this._showPromiseReject = null; + } + this._dispatchEvent(EventType.error, err); + }); } - return false; - }, - setTabBarBadge, - setTabBarItem, - setTabBarStyle, - hideTabBar, - showTabBar, - append(webview) { - tabBar && - tabBar.append({ - id: webview.id, - }, ({ code }) => { - if (code !== 0) { - setTimeout(() => { - this.append(webview); - }, 20); + } + _showAd() { + if (this._adInstance !== null && this._isLoaded === true) { + this._adInstance.show({ + adpid: this._adpid, + }, () => { + this._isLoaded = false; + }, (err) => { + this._isLoaded = false; + if (this._showPromiseReject != null) { + this._showPromiseReject(this._createError(err)); + this._showPromiseReject = null; } + this._dispatchEvent(EventType.error, err); }); - }, - get visible() { - return visible; - }, - get height() { - return ((config && config.height ? parseFloat(config.height) : TABBAR_HEIGHT) + - plus.navigator.getSafeAreaInsets().deviceBottom); - }, - // tabBar是否遮挡内容区域 - get cover() { - const array = ['extralight', 'light', 'dark']; - return isIOS && array.indexOf(config.blurEffect) >= 0; - }, - setStyle({ mask }) { - tabBar.setMask({ - color: mask, - }); - }, - addEventListener(_name, callback) { - maskClickCallback.push(callback); - }, - removeEventListener(_name, callback) { - const callbackIndex = maskClickCallback.indexOf(callback); - maskClickCallback.splice(callbackIndex, 1); - }, - }; - - function initTabBar() { - const { tabBar } = __uniConfig; - const len = tabBar && tabBar.list && tabBar.list.length; - if (!len) { - return; + } } - const { entryPagePath } = __uniConfig; - tabBar.selectedIndex = 0; - const selected = tabBar.list.findIndex((page) => page.pagePath === entryPagePath); - tabBar$1.init(tabBar, (item, index) => { - uni.switchTab({ - url: '/' + item.pagePath, - openType: 'switchTab', - from: 'tabBar', - success() { - invokeHook('onTabItemTap', { - index, - text: item.text, - pagePath: item.pagePath, - }); - }, - }); - }); - if (selected !== -1) { - // 取当前 tab 索引值 - tabBar.selectedIndex = selected; - selected !== 0 && tabBar$1.switchTab(entryPagePath); + _createError(err) { + return new Error(JSON.stringify(err)); } - } - - function backbuttonListener() { - uni.navigateBack({ - from: 'backbutton', - }); - } + } + const createInteractiveAd = (defineSyncApi(API_CREATE_INTERACTIVE_AD, (options) => { + return new InteractiveAd(options); + }, CreateInteractiveAdProtocol, CreateInteractiveAdOptions)); - function initGlobalEvent() { - const plusGlobalEvent = plus.globalEvent; - const weexGlobalEvent = weex.requireModule('globalEvent'); - const emit = UniServiceJSBridge.emit; - if (weex.config.preload) { - plus.key.addEventListener('backbutton', backbuttonListener); + let pendingNavigator = false; + function setPendingNavigator(path, callback, msg) { + pendingNavigator = { + path, + nvue: getRouteMeta(path).isNVue, + callback, + }; + if ((process.env.NODE_ENV !== 'production')) { + console.log(`nextNavigator:${path} ${msg}`); + } + } + function navigate(path, callback, isAppLaunch) { + if (!isAppLaunch && pendingNavigator) { + return console.error(`Waiting to navigate to: ${pendingNavigator.path}, do not operate continuously: ${path}.`); + } + if (__uniConfig.renderer === 'native') { + // 纯原生无需wait逻辑 + // 如果是首页还未初始化,需要等一等,其他无需等待 + if (getCurrentPages().length === 0) { + return setPendingNavigator(path, callback, 'waitForReady'); + } + return callback(); + } + // 未创建 preloadWebview 或 preloadWebview 已被使用 + const waitPreloadWebview = !preloadWebview || (preloadWebview && preloadWebview.__uniapp_route); + // 已创建未 loaded + const waitPreloadWebviewReady = preloadWebview && !preloadWebview.loaded; + if (waitPreloadWebview || waitPreloadWebviewReady) { + setPendingNavigator(path, callback, waitPreloadWebview ? 'waitForCreate' : 'waitForReady'); } else { - plusGlobalEvent.addEventListener('splashclosed', () => { - plus.key.addEventListener('backbutton', backbuttonListener); - }); + callback(); + } + if (waitPreloadWebviewReady) { + onWebviewReady(preloadWebview.id, pendingNavigate); } - plusGlobalEvent.addEventListener('pause', () => { - emit('onAppEnterBackground'); - }); - plusGlobalEvent.addEventListener('resume', () => { - emit('onAppEnterForeground'); - }); - weexGlobalEvent.addEventListener('uistylechange', function (event) { - const args = { - theme: event.uistyle, - }; - emit('onThemeChange', args); - }); - plusGlobalEvent.addEventListener('plusMessage', subscribePlusMessage); - // nvue webview post message - plusGlobalEvent.addEventListener('WebviewPostMessage', subscribePlusMessage); } - function subscribePlusMessage({ data, }) { - if (data && data.type) { - UniServiceJSBridge.subscribeHandler('plusMessage.' + data.type, data.args); + function pendingNavigate() { + if (!pendingNavigator) { + return; + } + const { callback } = pendingNavigator; + if ((process.env.NODE_ENV !== 'production')) { + console.log(`pendingNavigate:${pendingNavigator.path}`); } + pendingNavigator = false; + return callback(); } - function onPlusMessage(type, callback, once = false) { - UniServiceJSBridge.subscribe('plusMessage.' + type, callback, once); + function navigateFinish() { + if (__uniConfig.renderer === 'native') { + if (!pendingNavigator) { + return; + } + if (pendingNavigator.nvue) { + return pendingNavigate(); + } + return; + } + // 创建预加载 + const preloadWebview = createPreloadWebview(); + if ((process.env.NODE_ENV !== 'production')) { + console.log(`navigateFinish.preloadWebview:${preloadWebview.id}`); + } + if (!pendingNavigator) { + return; + } + if (pendingNavigator.nvue) { + return pendingNavigate(); + } + preloadWebview.loaded + ? pendingNavigator.callback() + : onWebviewReady(preloadWebview.id, pendingNavigate); } - function initAppLaunch(appVm) { - const args = { - path: __uniConfig.entryPagePath, - query: {}, - scene: 1001, + function showWebview(webview, animationType, animationDuration, showCallback, delay) { + if (typeof delay === 'undefined') { + delay = webview.nvue ? 0 : 100; + } + if ((process.env.NODE_ENV !== 'production')) { + console.log(`[show][${Date.now()}]`, delay); + } + const execShowCallback = function () { + if (execShowCallback._called) { + if ((process.env.NODE_ENV !== 'production')) { + console.log('execShowCallback.prevent'); + } + return; + } + execShowCallback._called = true; + showCallback && showCallback(); + navigateFinish(); }; - invokeHook(appVm, 'onLaunch', args); - invokeHook(appVm, 'onShow', args); - } - - // 统一处理路径 - function getPath(path) { - path = path.replace(/\/$/, ''); - return path.indexOf('_') === 0 - ? plus.io.convertLocalFileSystemURL(path) - : path; - } - function clearTempFile() { - const basePath = getPath(TEMP_PATH_BASE); - const tempPath = getPath(TEMP_PATH); - // 获取父目录 - const dirParts = tempPath.split('/'); - dirParts.pop(); - const dirPath = dirParts.join('/'); - plus.io.resolveLocalFileSystemURL(plus.io.convertAbsoluteFileSystem(dirPath), (entry) => { - const reader = entry.createReader(); - reader.readEntries(function (entry) { - // plus.d.ts 类型不对 - const entries = entry; - if (entries && entries.length) { - entries.forEach(function (entry) { - if (entry.isDirectory && - entry.fullPath.indexOf(basePath) === 0 && - entry.fullPath.indexOf(tempPath) !== 0) { - entry.removeRecursively(); - } - }); + execShowCallback._called = false; + setTimeout(() => { + const timer = setTimeout(() => { + if ((process.env.NODE_ENV !== 'production')) { + console.log(`[show.callback.timer][${Date.now()}]`); + } + execShowCallback(); + }, animationDuration + 150); + webview.show(animationType, animationDuration, () => { + if ((process.env.NODE_ENV !== 'production')) { + console.log(`[show.callback][${Date.now()}]`); + } + if (!execShowCallback._called) { + clearTimeout(timer); } + execShowCallback(); }); - }); + }, delay); } - let isLaunchWebviewReady = false; // 目前首页双向确定 ready,可能会导致触发两次 onWebviewReady(主要是 Android) - function subscribeWebviewReady(_data, pageId) { - const isLaunchWebview = pageId === '1'; - if (isLaunchWebview && isLaunchWebviewReady) { - if ((process.env.NODE_ENV !== 'production')) { - console.log('[uni-app] onLaunchWebviewReady.prevent'); + const BRIDGE_NODE_SYNC = 'nodeSync'; + const ACTION_TYPE_PAGE_CREATE = 1; + const ACTION_TYPE_PAGE_CREATED = 2; + const ACTION_TYPE_CREATE = 3; + const ACTION_TYPE_INSERT = 4; + const ACTION_TYPE_REMOVE = 5; + const ACTION_TYPE_SET_ATTRIBUTE = 6; + const ACTION_TYPE_REMOVE_ATTRIBUTE = 7; + const ACTION_TYPE_SET_TEXT = 8; + class UniPageNode extends UniNode { + constructor(pageId, options, setup = false) { + super(NODE_TYPE_PAGE, '#page', null); + this._id = 1; + this.updateActions = []; + this.nodeId = 0; + this.pageId = pageId; + this.pageNode = this; + this.createAction = [ACTION_TYPE_PAGE_CREATE, options]; + this.createdAction = [ACTION_TYPE_PAGE_CREATED]; + setup && this.setup(); + } + onCreate(thisNode, nodeName) { + pushCreateAction(this, thisNode.nodeId, nodeName); + return thisNode; + } + onInsertBefore(thisNode, newChild, index) { + pushInsertAction(this, newChild, thisNode.nodeId, index); + return newChild; + } + onRemoveChild(thisNode, oldChild) { + pushRemoveAction(this, oldChild.nodeId, thisNode.nodeId); + return oldChild; + } + onSetAttribute(thisNode, qualifiedName, value) { + if (thisNode.parentNode) { + pushSetAttributeAction(this, thisNode.nodeId, qualifiedName, value); } - return; } - if (isLaunchWebview) { - // 首页 - isLaunchWebviewReady = true; - setPreloadWebview(plus.webview.getLaunchWebview()); + onRemoveAttribute(thisNode, qualifiedName) { + if (thisNode.parentNode) { + pushRemoveAttributeAction(this, thisNode.nodeId, qualifiedName); + } } - else if (!preloadWebview) { - // preloadWebview 不存在,重新加载一下 - setPreloadWebview(plus.webview.getWebviewById(pageId)); + onTextContent(thisNode, text) { + if (thisNode.parentNode) { + pushSetTextAction(this, thisNode.nodeId, text); + } } - if (preloadWebview.id !== pageId) { - return console.error(`webviewReady[${preloadWebview.id}][${pageId}] not match`); + onNodeValue(thisNode, val) { + if (thisNode.parentNode) { + pushSetTextAction(this, thisNode.nodeId, val); + } } - preloadWebview.loaded = true; // 标记已 ready - UniServiceJSBridge.emit(ON_WEBVIEW_READY + '.' + pageId); - isLaunchWebview && onLaunchWebviewReady(); - } - function onLaunchWebviewReady() { - const { autoclose, alwaysShowBeforeRender } = __uniConfig.splashscreen; - if (autoclose && !alwaysShowBeforeRender) { - plus.navigator.closeSplashscreen(); + genId() { + return this._id++; } - const entryPagePath = '/' + __uniConfig.entryPagePath; - const routeOptions = getRouteOptions(entryPagePath); - if (!routeOptions.meta.isNVue) { - // 非 nvue 首页,需要主动跳转 - const args = { - url: entryPagePath + (__uniConfig.entryPageQuery || ''), - openType: 'appLaunch', - }; - if (routeOptions.meta.isTabBar) { - return uni.switchTab(args); + push(action) { + this.updateActions.push(action); + } + restore() { + this.push(this.createAction); + // TODO restore children + this.push(this.createdAction); + } + setup() { + this.send([this.createAction]); + } + mounted() { + const { updateActions, createdAction } = this; + updateActions.unshift(createdAction); + this.update(); + } + update() { + const { updateActions } = this; + if (updateActions.length) { + this.send(updateActions); + updateActions.length = 0; } - return uni.navigateTo(args); } - } - - function initSubscribeHandlers() { - const { subscribe, subscribeHandler } = UniServiceJSBridge; - onPlusMessage('subscribeHandler', ({ type, data, pageId }) => { - subscribeHandler(type, data, pageId); - }); - if (__uniConfig.renderer !== 'native') { - // 非纯原生 - subscribe(ON_WEBVIEW_READY, subscribeWebviewReady); + send(action) { + UniServiceJSBridge.publishHandler(BRIDGE_NODE_SYNC, action, this.pageId); } + } + function pushCreateAction(pageNode, nodeId, nodeName) { + pageNode.push([ACTION_TYPE_CREATE, nodeId, nodeName]); + } + function pushInsertAction(pageNode, newChild, parentNodeId, index) { + pageNode.push([ + ACTION_TYPE_INSERT, + newChild.nodeId, + parentNodeId, + index, + newChild.toJSON({ attr: true }), + ]); + } + function pushRemoveAction(pageNode, nodeId, parentNodeId) { + pageNode.push([ACTION_TYPE_REMOVE, nodeId, parentNodeId]); + } + function pushSetAttributeAction(pageNode, nodeId, name, value) { + pageNode.push([ACTION_TYPE_SET_ATTRIBUTE, nodeId, name, value]); + } + function pushRemoveAttributeAction(pageNode, nodeId, name) { + pageNode.push([ACTION_TYPE_REMOVE_ATTRIBUTE, nodeId, name]); + } + function pushSetTextAction(pageNode, nodeId, text) { + pageNode.push([ACTION_TYPE_SET_TEXT, nodeId, text]); + } + function createPageNode(pageId, pageOptions, setup) { + return new UniPageNode(pageId, pageOptions, setup); } - let appCtx; - const defaultApp = { - globalData: {}, - }; - function registerApp(appVm) { - appCtx = appVm; - appCtx.$vm = appVm; - extend(appCtx, defaultApp); // 拷贝默认实现 - const { $options } = appVm; - if ($options) { - appCtx.globalData = extend($options.globalData || {}, appCtx.globalData); - } - initEntry(); - initTabBar(); - initGlobalEvent(); - initSubscribeHandlers(); - initAppLaunch(appVm); - // 10s后清理临时文件 - setTimeout(clearTempFile, 10000); - __uniConfig.ready = true; + const pages = []; + function addCurrentPage(page) { + pages.push(page); + } + function getCurrentPages$1() { + const curPages = []; + pages.forEach((page) => { + if (page.__isTabBar) { + if (page.$.__isActive) { + curPages.push(page); + } + } + else { + curPages.push(page); + } + }); + return curPages; } - var __vuePlugin = { - install(app, runtime) { - // @ts-expect-error 赋值全局对象 jsRuntime - extend(jsRuntime, runtime); - initMount(app); - initApp(app); - initService(app); - }, - }; - function initMount(app) { - const oldMount = app.mount; - app.mount = (rootContainer) => { - const instance = oldMount.call(app, rootContainer); - if (rootContainer === '#app') { - registerApp(instance); + function setupPage(component, { pageId, pagePath, pageQuery, pageInstance }) { + const oldSetup = component.setup; + component.setup = (_props, ctx) => { + if ((process.env.NODE_ENV !== 'production')) { + console.log(`${pagePath} setup`); + } + const instance = vue.getCurrentInstance(); + const pageVm = instance.proxy; + pageVm.$page = pageInstance; + addCurrentPage(initScope(pageId, pageVm)); + if (oldSetup) { + return oldSetup(pageQuery, ctx); } - return instance; }; + return component; + } + function initScope(pageId, vm) { + vm.$scope = { + $getAppWebview() { + return plus.webview.getWebviewById(String(pageId)); + }, + }; + return vm; } const pagesMap = new Map(); @@ -6576,17 +6650,18 @@ var serviceContext = (function (vue) { pagesMap.set(pagePath, once(createFactory(component))); } function createPage(pageId, pagePath, pageQuery, pageInstance, pageOptions) { - return vue.createApp(pagesMap.get(pagePath)(), { + return vue.createApp(pagesMap.get(pagePath)({ + pageId, pagePath, pageQuery, pageInstance, - }) + })) .use(__vuePlugin) - .mount(createPageNode(pageId, pageOptions)); + .mount(createPageNode(pageId, pageOptions, true)); } function createFactory(component) { - return () => { - return setupPage(component); + return (props) => { + return setupPage(component, props); }; } @@ -6618,7 +6693,7 @@ var serviceContext = (function (vue) { : 0; } - function registerPage({ path, query, openType, webview, }) { + function registerPage({ url, path, query, openType, webview, vm, }) { // fast 模式,nvue 首页时,会在nvue中主动调用registerPage并传入首页webview,此时初始化一下首页(因为此时可能还未调用registerApp) if (webview) { initEntry(); @@ -6633,14 +6708,22 @@ var serviceContext = (function (vue) { webview.nvue = routeOptions.meta.isNVue; } routeOptions.meta.id = parseInt(webview.id); + const isTabBar = !!routeOptions.meta.isTabBar; + if (isTabBar) { + tabBar$1.append(webview); + } if ((process.env.NODE_ENV !== 'production')) { console.log(`[uni-app] registerPage(${path},${webview.id})`); } initWebview(webview, path, query, routeOptions.meta); const route = path.substr(1); webview.__uniapp_route = route; + const pageInstance = initPageInternalInstance(url, query, routeOptions.meta); if (!webview.nvue) { - createPage(parseInt(webview.id), route, query, null, initPageOptions(routeOptions)); + createPage(parseInt(webview.id), route, query, pageInstance, initPageOptions(routeOptions)); + } + else { + vm && addCurrentPage(vm); } return webview; } @@ -6794,9 +6877,11 @@ var serviceContext = (function (vue) { getUserProfile: getUserProfile, preLogin: preLogin, closeAuthView: closeAuthView, + registerRuntime: registerRuntime, share: share, shareWithSystem: shareWithSystem, requestPayment: requestPayment, + __vuePlugin: __vuePlugin, createRewardedVideoAd: createRewardedVideoAd, createFullScreenVideoAd: createFullScreenVideoAd, createInterstitialAd: createInterstitialAd, @@ -6823,10 +6908,10 @@ var serviceContext = (function (vue) { }); } - // ;(uni as any).__$wx__ = uni var index = { uni: uni$1, - __vuePlugin, + getApp: getApp$1, + getCurrentPages: getCurrentPages$1, __definePage: definePage, __registerApp: registerApp, __registerPage: registerPage, @@ -6835,7 +6920,7 @@ var serviceContext = (function (vue) { return index; -}(jsRuntime)); +}(Vue)); const uni = serviceContext.uni; const getApp = serviceContext.getApp; const getCurrentPages = serviceContext.getCurrentPages; diff --git a/packages/uni-app-plus/dist/uni-app-view.umd.js b/packages/uni-app-plus/dist/uni-app-view.umd.js index ccde7bdf58..0acfd54a5e 100644 --- a/packages/uni-app-plus/dist/uni-app-view.umd.js +++ b/packages/uni-app-plus/dist/uni-app-view.umd.js @@ -5608,7 +5608,19 @@ }; function initBridge(subscribeNamespace) { const emitter = new E(); - return extend(emitter, { + return { + on(event, callback) { + return emitter.on(event, callback); + }, + once(event, callback) { + return emitter.once(event, callback); + }, + off(event, callback) { + return emitter.off(event, callback); + }, + emit(event, ...args) { + return emitter.emit(event, ...args); + }, subscribe(event, callback, once = false) { emitter[once ? "once" : "on"](`${subscribeNamespace}.${event}`, callback); }, @@ -5621,7 +5633,7 @@ } emitter.emit(`${subscribeNamespace}.${event}`, args, pageId); } - }); + }; } const ViewJSBridge = /* @__PURE__ */ initBridge("service"); function PolySymbol(name) { @@ -5693,11 +5705,6 @@ fromRouteArray.splice(fromRouteArray.length - i - 1, i + 1); return "/" + fromRouteArray.concat(toRouteArray).join("/"); } - /* @__PURE__ */ extend(initBridge("view"), { - invokeOnCallback(name, res) { - return UniServiceJSBridge.emit("api." + name, res); - } - }); function converPx(value) { if (/^-?\d+[ur]px$/i.test(value)) { return value.replace(/(^-?\d+)[ur]px$/i, (text, num) => { diff --git a/packages/uni-app-plus/src/service/api/index.ts b/packages/uni-app-plus/src/service/api/index.ts index d4e30ee832..adc886e2fa 100644 --- a/packages/uni-app-plus/src/service/api/index.ts +++ b/packages/uni-app-plus/src/service/api/index.ts @@ -38,8 +38,10 @@ export * from './ui/popup/showToast' export * from './plugin/getProvider' export * from './plugin/oauth' +export * from './plugin/registerRuntime' export * from './plugin/share' export * from './plugin/requestPayment' +export * from './plugin/vuePlugin' export * from './ad/rewardedVideoAd' export * from './ad/fullScreenVideoAd' diff --git a/packages/uni-app-plus/src/service/api/plugin/registerRuntime.ts b/packages/uni-app-plus/src/service/api/plugin/registerRuntime.ts new file mode 100644 index 0000000000..6d7cdab65c --- /dev/null +++ b/packages/uni-app-plus/src/service/api/plugin/registerRuntime.ts @@ -0,0 +1,21 @@ +import { extend } from '@vue/shared' +import { defineSyncApi } from '@dcloudio/uni-api' +import { ComponentInternalInstance } from 'vue' + +interface JsRuntime { + injectHook: ( + type: string, + hook: Function, + target: ComponentInternalInstance | null, + prepend: boolean + ) => Function | undefined + createApp: typeof createApp +} + +export const registerRuntime = defineSyncApi<(runtime: JsRuntime) => void>( + 'registerRuntime', + (runtime) => { + // @ts-expect-error + extend(jsRuntime, runtime) + } +) diff --git a/packages/uni-app-plus/src/service/api/plugin/vuePlugin.ts b/packages/uni-app-plus/src/service/api/plugin/vuePlugin.ts new file mode 100644 index 0000000000..7f84fa46e8 --- /dev/null +++ b/packages/uni-app-plus/src/service/api/plugin/vuePlugin.ts @@ -0,0 +1 @@ +export { default as __vuePlugin } from '../../framework/plugin' diff --git a/packages/uni-app-plus/src/service/framework/app/index.ts b/packages/uni-app-plus/src/service/framework/app/index.ts index 56e364b878..0ebee76cf6 100644 --- a/packages/uni-app-plus/src/service/framework/app/index.ts +++ b/packages/uni-app-plus/src/service/framework/app/index.ts @@ -1,6 +1,8 @@ import { ComponentPublicInstance } from 'vue' import { extend } from '@vue/shared' +import { initService } from '@dcloudio/uni-core' + import { initEntry } from './initEntry' import { initTabBar } from './initTabBar' import { initGlobalEvent } from './initGlobalEvent' @@ -13,7 +15,24 @@ const defaultApp = { globalData: {}, } +export function getApp({ allowDefault = false } = {}) { + if (appCtx) { + // 真实的 App 已初始化 + return appCtx + } + if (allowDefault) { + // 返回默认实现 + return defaultApp + } + console.error( + '[warn]: getApp() failed. Learn more: https://uniapp.dcloud.io/collocation/frame/window?id=getapp.' + ) +} + export function registerApp(appVm: ComponentPublicInstance) { + if (__DEV__) { + console.log('registerApp') + } appCtx = appVm appCtx.$vm = appVm @@ -24,6 +43,8 @@ export function registerApp(appVm: ComponentPublicInstance) { appCtx.globalData = extend($options.globalData || {}, appCtx.globalData) } + initService() + initEntry() initTabBar() initGlobalEvent() diff --git a/packages/uni-app-plus/src/service/framework/app/initGlobalEvent.ts b/packages/uni-app-plus/src/service/framework/app/initGlobalEvent.ts index 4253b40fa0..77981d6aad 100644 --- a/packages/uni-app-plus/src/service/framework/app/initGlobalEvent.ts +++ b/packages/uni-app-plus/src/service/framework/app/initGlobalEvent.ts @@ -41,6 +41,9 @@ function subscribePlusMessage({ }: { data: { type: string; args: Record } }) { + if (__DEV__) { + console.log('plusMessage:' + JSON.stringify(data)) + } if (data && data.type) { UniServiceJSBridge.subscribeHandler('plusMessage.' + data.type, data.args) } diff --git a/packages/uni-app-plus/src/service/framework/page/define.ts b/packages/uni-app-plus/src/service/framework/page/define.ts index f9d704efe3..ac566cea7a 100644 --- a/packages/uni-app-plus/src/service/framework/page/define.ts +++ b/packages/uni-app-plus/src/service/framework/page/define.ts @@ -13,29 +13,33 @@ export function definePage(pagePath: string, component: VueComponent) { } export interface PageProps { + pageId: number pagePath: string pageQuery: Record - pageInstance: unknown + pageInstance: Page.PageInstance['$page'] } export function createPage( pageId: number, pagePath: string, pageQuery: Record, - pageInstance: unknown, + pageInstance: Page.PageInstance['$page'], pageOptions: PageNodeOptions ) { - return createApp(pagesMap.get(pagePath)!(), { - pagePath, - pageQuery, - pageInstance, - }) + return createApp( + pagesMap.get(pagePath)!({ + pageId, + pagePath, + pageQuery, + pageInstance, + }) + ) .use(__vuePlugin) - .mount(createPageNode(pageId, pageOptions) as unknown as Element) + .mount(createPageNode(pageId, pageOptions, true) as unknown as Element) } function createFactory(component: VueComponent) { - return () => { - return setupPage(component) + return (props: PageProps) => { + return setupPage(component, props) } } diff --git a/packages/uni-app-plus/src/service/framework/page/getCurrentPages.ts b/packages/uni-app-plus/src/service/framework/page/getCurrentPages.ts new file mode 100644 index 0000000000..fa23894cea --- /dev/null +++ b/packages/uni-app-plus/src/service/framework/page/getCurrentPages.ts @@ -0,0 +1,21 @@ +import { ComponentPublicInstance } from 'vue' + +const pages: ComponentPublicInstance[] = [] + +export function addCurrentPage(page: ComponentPublicInstance) { + pages.push(page) +} + +export function getCurrentPages() { + const curPages: ComponentPublicInstance[] = [] + pages.forEach((page) => { + if (page.__isTabBar) { + if (page.$.__isActive) { + curPages.push(page) + } + } else { + curPages.push(page) + } + }) + return curPages +} diff --git a/packages/uni-app-plus/src/service/framework/page/index.ts b/packages/uni-app-plus/src/service/framework/page/index.ts index ed18c36f26..f77cb3d1ac 100644 --- a/packages/uni-app-plus/src/service/framework/page/index.ts +++ b/packages/uni-app-plus/src/service/framework/page/index.ts @@ -1,3 +1,3 @@ -export * from './define' -export * from './register' -plus.webview.create +export { definePage } from './define' +export { registerPage } from './register' +export { getCurrentPages } from './getCurrentPages' 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 4f888f3626..f0da836f92 100644 --- a/packages/uni-app-plus/src/service/framework/page/register.ts +++ b/packages/uni-app-plus/src/service/framework/page/register.ts @@ -7,6 +7,9 @@ import { createPage } from './define' import { PageNodeOptions } from '../dom/Page' import { getStatusbarHeight } from '../../../helpers/statusBar' import tabBar from '../app/tabBar' +import { addCurrentPage } from './getCurrentPages' +import { initPageInternalInstance } from '@dcloudio/uni-core' +import { ComponentPublicInstance } from 'vue' export type OpenType = | 'navigateTo' @@ -22,14 +25,17 @@ interface RegisterPageOptions { query: Record openType: OpenType webview?: PlusWebviewWebviewObject + vm?: ComponentPublicInstance // nvue vm instance // eventChannel: unknown } export function registerPage({ + url, path, query, openType, webview, + vm, }: RegisterPageOptions) { // fast 模式,nvue 首页时,会在nvue中主动调用registerPage并传入首页webview,此时初始化一下首页(因为此时可能还未调用registerApp) if (webview) { @@ -48,6 +54,11 @@ export function registerPage({ routeOptions.meta.id = parseInt(webview.id!) + const isTabBar = !!routeOptions.meta.isTabBar + if (isTabBar) { + tabBar.append(webview) + } + if (__DEV__) { console.log(`[uni-app] registerPage(${path},${webview.id})`) } @@ -58,14 +69,18 @@ export function registerPage({ ;(webview as any).__uniapp_route = route + const pageInstance = initPageInternalInstance(url, query, routeOptions.meta) + if (!(webview as any).nvue) { createPage( parseInt(webview.id!), route, query, - null, + pageInstance, initPageOptions(routeOptions) ) + } else { + vm && addCurrentPage(vm) } return webview } diff --git a/packages/uni-app-plus/src/service/framework/page/routeOptions.ts b/packages/uni-app-plus/src/service/framework/page/routeOptions.ts index 02168be3a8..39e94996e1 100644 --- a/packages/uni-app-plus/src/service/framework/page/routeOptions.ts +++ b/packages/uni-app-plus/src/service/framework/page/routeOptions.ts @@ -1,5 +1,5 @@ import { getRouteOptions, initRouteMeta } from '@dcloudio/uni-core' -import { OpenType } from '.' +import { OpenType } from './register' export function initRouteOptions(path: string, openType: OpenType) { // 需要序列化一遍 diff --git a/packages/uni-app-plus/src/service/framework/page/setup.ts b/packages/uni-app-plus/src/service/framework/page/setup.ts index 3df8645c15..223b0ddacf 100644 --- a/packages/uni-app-plus/src/service/framework/page/setup.ts +++ b/packages/uni-app-plus/src/service/framework/page/setup.ts @@ -1,18 +1,32 @@ +import { ComponentPublicInstance, getCurrentInstance } from 'vue' import { PageProps, VueComponent } from './define' +import { addCurrentPage } from './getCurrentPages' -export function setupPage(component: VueComponent) { - if (__DEV__) { - console.log(`setupPage`) - } +export function setupPage( + component: VueComponent, + { pageId, pagePath, pageQuery, pageInstance }: PageProps +) { const oldSetup = component.setup - component.setup = (props, ctx) => { - const { pagePath, pageQuery } = props as unknown as PageProps + component.setup = (_props, ctx) => { if (__DEV__) { console.log(`${pagePath} setup`) } + const instance = getCurrentInstance()! + const pageVm = instance.proxy! + pageVm.$page = pageInstance + addCurrentPage(initScope(pageId, pageVm)) if (oldSetup) { return oldSetup(pageQuery as any, ctx) } } return component } + +function initScope(pageId: number, vm: ComponentPublicInstance) { + vm.$scope = { + $getAppWebview() { + return plus.webview.getWebviewById(String(pageId)) + }, + } + return vm +} diff --git a/packages/uni-app-plus/src/service/framework/plugin/index.ts b/packages/uni-app-plus/src/service/framework/plugin/index.ts index 14992146f7..21684931e3 100644 --- a/packages/uni-app-plus/src/service/framework/plugin/index.ts +++ b/packages/uni-app-plus/src/service/framework/plugin/index.ts @@ -1,27 +1,13 @@ -import { App, ComponentInternalInstance } from 'vue' -import { extend } from '@vue/shared' +import { App } from 'vue' import { initApp } from '@dcloudio/uni-vue' -import { initService } from '@dcloudio/uni-core' +import { initServicePlugin } from '@dcloudio/uni-core' import { registerApp } from '../app' -interface JsRuntime { - injectHook: ( - type: string, - hook: Function, - target: ComponentInternalInstance | null, - prepend: boolean - ) => Function | undefined - createApp: typeof createApp -} - export default { - install(app: App, runtime: JsRuntime) { - // @ts-expect-error 赋值全局对象 jsRuntime - extend(jsRuntime, runtime) - + install(app: App) { initMount(app) initApp(app) - initService(app) + initServicePlugin(app) }, } diff --git a/packages/uni-app-plus/src/service/framework/runtime.ts b/packages/uni-app-plus/src/service/framework/runtime.ts new file mode 100644 index 0000000000..089ec21592 --- /dev/null +++ b/packages/uni-app-plus/src/service/framework/runtime.ts @@ -0,0 +1,16 @@ +import { ComponentInternalInstance } from 'vue' +import { extend } from '@vue/shared' +interface JsRuntime { + injectHook: ( + type: string, + hook: Function, + target: ComponentInternalInstance | null, + prepend: boolean + ) => Function | undefined + createApp: typeof createApp +} + +export function defineRuntime(runtime: JsRuntime) { + // @ts-expect-error + extend(jsRuntime, runtime) +} diff --git a/packages/uni-app-plus/src/service/index.ts b/packages/uni-app-plus/src/service/index.ts index 3d251029b0..434da35643 100644 --- a/packages/uni-app-plus/src/service/index.ts +++ b/packages/uni-app-plus/src/service/index.ts @@ -1,16 +1,16 @@ import * as uni from './api' import { UniServiceJSBridge } from './bridge' -import { registerApp as __registerApp } from './framework/app' +import { getApp, registerApp as __registerApp } from './framework/app' import { definePage as __definePage, registerPage as __registerPage, + getCurrentPages, } from './framework/page' -import __vuePlugin from './framework/plugin' -// ;(uni as any).__$wx__ = uni export default { uni, - __vuePlugin, + getApp, + getCurrentPages, __definePage, __registerApp, __registerPage, diff --git a/packages/uni-app-vite/dist/plugin.js b/packages/uni-app-vite/dist/plugin.js index 53b9178317..684c40790e 100644 --- a/packages/uni-app-vite/dist/plugin.js +++ b/packages/uni-app-vite/dist/plugin.js @@ -23,9 +23,12 @@ exports.UniAppPlugin = { formats: ['iife'], }, rollupOptions: { - // external: ['vue'], + external: ['vue'], output: { entryFileNames: 'app-service.js', + globals: { + vue: 'Vue', + }, }, }, }, diff --git a/packages/uni-app-vite/dist/plugins/mainJs.js b/packages/uni-app-vite/dist/plugins/mainJs.js index 256da71a26..fa136dbbef 100644 --- a/packages/uni-app-vite/dist/plugins/mainJs.js +++ b/packages/uni-app-vite/dist/plugins/mainJs.js @@ -13,7 +13,7 @@ function uniMainJsPlugin() { ? createApp(code) : createLegacyApp(code); return { - code: `import './pages.json.js';` + JS_RUNTIME_CODE + code, + code: `import './pages.json.js';` + code, map: this.getCombinedSourcemap(), }; } @@ -22,10 +22,9 @@ function uniMainJsPlugin() { }); } exports.uniMainJsPlugin = uniMainJsPlugin; -const JS_RUNTIME_CODE = `import {injectHook as __injectHook__,createApp as __createApp__} from 'vue';const __RUNTIME__ = {injectHook:__injectHook__,createApp:__createApp__};`; function createApp(code) { - return `const __app__=createApp().app;__app__._component.render=()=>{};__app__.use(__vuePlugin,__RUNTIME__).mount("#app");${code.replace('createSSRApp', 'createVueApp as createSSRApp')}`; + return `const __app__=createApp().app;__app__._component.render=()=>{};__app__.use(uni.__vuePlugin).mount("#app");${code.replace('createSSRApp', 'createVueApp as createSSRApp')}`; } function createLegacyApp(code) { - return `function createApp(rootComponent,rootProps){const app=createVueApp(rootComponent,rootProps).use(__vuePlugin,__RUNTIME__);app.render=()=>{};const oldMount=app.mount;app.mount=(container)=>{const appVm=oldMount.call(app,container);return appVm;};return app;};${code.replace('createApp', 'createVueApp')}`; + return `function createApp(rootComponent,rootProps){const app=createVueApp(rootComponent,rootProps).use(uni.__vuePlugin);app.render=()=>{};const oldMount=app.mount;app.mount=(container)=>{const appVm=oldMount.call(app,container);return appVm;};return app;};${code.replace('createApp', 'createVueApp')}`; } diff --git a/packages/uni-app-vite/src/plugin.ts b/packages/uni-app-vite/src/plugin.ts index 89a9d5d795..14c9526602 100644 --- a/packages/uni-app-vite/src/plugin.ts +++ b/packages/uni-app-vite/src/plugin.ts @@ -31,12 +31,12 @@ export const UniAppPlugin: UniVitePlugin = { formats: ['iife'], }, rollupOptions: { - // external: ['vue'], + external: ['vue'], output: { entryFileNames: 'app-service.js', - // globals: { - // vue: 'Vue', - // }, + globals: { + vue: 'Vue', + }, }, }, }, diff --git a/packages/uni-app-vite/src/plugins/mainJs.ts b/packages/uni-app-vite/src/plugins/mainJs.ts index 923981cad1..52ba85a1f7 100644 --- a/packages/uni-app-vite/src/plugins/mainJs.ts +++ b/packages/uni-app-vite/src/plugins/mainJs.ts @@ -11,7 +11,7 @@ export function uniMainJsPlugin() { ? createApp(code) : createLegacyApp(code) return { - code: `import './pages.json.js';` + JS_RUNTIME_CODE + code, + code: `import './pages.json.js';` + code, map: this.getCombinedSourcemap(), } } @@ -20,17 +20,15 @@ export function uniMainJsPlugin() { }) } -const JS_RUNTIME_CODE = `import {injectHook as __injectHook__,createApp as __createApp__} from 'vue';const __RUNTIME__ = {injectHook:__injectHook__,createApp:__createApp__};` - function createApp(code: string) { - return `const __app__=createApp().app;__app__._component.render=()=>{};__app__.use(__vuePlugin,__RUNTIME__).mount("#app");${code.replace( + return `const __app__=createApp().app;__app__._component.render=()=>{};__app__.use(uni.__vuePlugin).mount("#app");${code.replace( 'createSSRApp', 'createVueApp as createSSRApp' )}` } function createLegacyApp(code: string) { - return `function createApp(rootComponent,rootProps){const app=createVueApp(rootComponent,rootProps).use(__vuePlugin,__RUNTIME__);app.render=()=>{};const oldMount=app.mount;app.mount=(container)=>{const appVm=oldMount.call(app,container);return appVm;};return app;};${code.replace( + return `function createApp(rootComponent,rootProps){const app=createVueApp(rootComponent,rootProps).use(uni.__vuePlugin);app.render=()=>{};const oldMount=app.mount;app.mount=(container)=>{const appVm=oldMount.call(app,container);return appVm;};return app;};${code.replace( 'createApp', 'createVueApp' )}` diff --git a/packages/uni-app-vue/build.json b/packages/uni-app-vue/build.json index 0042d27f2a..245935d47d 100644 --- a/packages/uni-app-vue/build.json +++ b/packages/uni-app-vue/build.json @@ -3,6 +3,10 @@ "input": { "src/service/index.ts": ["dist/service.runtime.esm.js"] }, + "output": { + "banner": "export default function vueFactory (exports) {\n", + "footer": "}" + }, "replacements": { "__VUE_OPTIONS_API__": "true", "__VUE_PROD_DEVTOOLS__": "false" diff --git a/packages/uni-app-vue/dist/service.runtime.esm.js b/packages/uni-app-vue/dist/service.runtime.esm.js index d1e3d676ad..be3f4495c0 100644 --- a/packages/uni-app-vue/dist/service.runtime.esm.js +++ b/packages/uni-app-vue/dist/service.runtime.esm.js @@ -1,3 +1,5 @@ +export default function vueFactory (exports) { + /** * Make a map and return a function for checking if a key * is in that map. @@ -11259,4 +11261,129 @@ function injectNativeTagCheck(app) { function onBeforeActivate() {} function onBeforeDeactivate() {} -export { BaseTransition, Comment$1 as Comment, Fragment, KeepAlive, Static, Suspense, Teleport, Text, Transition, TransitionGroup, callWithAsyncErrorHandling, callWithErrorHandling, camelize, capitalize, cloneVNode, compatUtils, computed$1 as computed, createApp, createBlock, createComment, createCommentVNode, createElement, createHydrationRenderer, createRenderer, createSSRApp, createSlots, createStaticVNode, createTextNode, createTextVNode, createVNode, createApp as createVueApp, customRef, defineAsyncComponent, defineComponent, defineEmit, defineEmits, defineProps, devtools, getCurrentInstance, getTransitionRawChildren, h, handleError, initCustomFormatter, inject, injectHook, isInSSRComponentSetup, isProxy, isReactive, isReadonly, isRef, isRuntimeOnly, isVNode, markRaw, mergeProps, nextTick, onActivated, onBeforeActivate, onBeforeDeactivate, onBeforeMount, onBeforeUnmount, onBeforeUpdate, onDeactivated, onErrorCaptured, onMounted, onRenderTracked, onRenderTriggered, onServerPrefetch, onUnmounted, onUpdated, openBlock, popScopeId, provide, proxyRefs, pushScopeId, queuePostFlushCb, reactive, readonly, ref, registerRuntimeCompiler, render, renderList, renderSlot, resolveComponent, resolveDirective, resolveDynamicComponent, resolveFilter, resolveTransitionHooks, setBlockTracking, setDevtoolsHook, setTransitionHooks, shallowReactive, shallowReadonly, shallowRef, ssrContextKey, ssrUtils, toDisplayString, toHandlerKey, toHandlers, toRaw, toRef, toRefs, transformVNodeArgs, triggerRef, unref, useContext, useCssModule, useCssVars, useSSRContext, useTransitionState, vModelText, vShow, version, warn, watch, watchEffect, withCtx, withDirectives, withKeys, withModifiers, withScopeId }; +var Vue = /*#__PURE__*/Object.freeze({ + __proto__: null, + BaseTransition: BaseTransition, + Comment: Comment$1, + Fragment: Fragment, + KeepAlive: KeepAlive, + Static: Static, + Suspense: Suspense, + Teleport: Teleport, + Text: Text, + Transition: Transition, + TransitionGroup: TransitionGroup, + callWithAsyncErrorHandling: callWithAsyncErrorHandling, + callWithErrorHandling: callWithErrorHandling, + camelize: camelize, + capitalize: capitalize, + cloneVNode: cloneVNode, + compatUtils: compatUtils, + computed: computed$1, + createApp: createApp, + createBlock: createBlock, + createComment: createComment, + createCommentVNode: createCommentVNode, + createElement: createElement, + createHydrationRenderer: createHydrationRenderer, + createRenderer: createRenderer, + createSSRApp: createSSRApp, + createSlots: createSlots, + createStaticVNode: createStaticVNode, + createTextNode: createTextNode, + createTextVNode: createTextVNode, + createVNode: createVNode, + createVueApp: createApp, + customRef: customRef, + defineAsyncComponent: defineAsyncComponent, + defineComponent: defineComponent, + defineEmit: defineEmit, + defineEmits: defineEmits, + defineProps: defineProps, + get devtools () { return devtools; }, + getCurrentInstance: getCurrentInstance, + getTransitionRawChildren: getTransitionRawChildren, + h: h, + handleError: handleError, + initCustomFormatter: initCustomFormatter, + inject: inject, + injectHook: injectHook, + get isInSSRComponentSetup () { return isInSSRComponentSetup; }, + isProxy: isProxy, + isReactive: isReactive, + isReadonly: isReadonly, + isRef: isRef, + isRuntimeOnly: isRuntimeOnly, + isVNode: isVNode, + markRaw: markRaw, + mergeProps: mergeProps, + nextTick: nextTick, + onActivated: onActivated, + onBeforeActivate: onBeforeActivate, + onBeforeDeactivate: onBeforeDeactivate, + onBeforeMount: onBeforeMount, + onBeforeUnmount: onBeforeUnmount, + onBeforeUpdate: onBeforeUpdate, + onDeactivated: onDeactivated, + onErrorCaptured: onErrorCaptured, + onMounted: onMounted, + onRenderTracked: onRenderTracked, + onRenderTriggered: onRenderTriggered, + onServerPrefetch: onServerPrefetch, + onUnmounted: onUnmounted, + onUpdated: onUpdated, + openBlock: openBlock, + popScopeId: popScopeId, + provide: provide, + proxyRefs: proxyRefs, + pushScopeId: pushScopeId, + queuePostFlushCb: queuePostFlushCb, + reactive: reactive, + readonly: readonly, + ref: ref, + registerRuntimeCompiler: registerRuntimeCompiler, + render: render, + renderList: renderList, + renderSlot: renderSlot, + resolveComponent: resolveComponent, + resolveDirective: resolveDirective, + resolveDynamicComponent: resolveDynamicComponent, + resolveFilter: resolveFilter, + resolveTransitionHooks: resolveTransitionHooks, + setBlockTracking: setBlockTracking, + setDevtoolsHook: setDevtoolsHook, + setTransitionHooks: setTransitionHooks, + shallowReactive: shallowReactive, + shallowReadonly: shallowReadonly, + shallowRef: shallowRef, + ssrContextKey: ssrContextKey, + ssrUtils: ssrUtils, + toDisplayString: toDisplayString, + toHandlerKey: toHandlerKey, + toHandlers: toHandlers, + toRaw: toRaw, + toRef: toRef, + toRefs: toRefs, + transformVNodeArgs: transformVNodeArgs, + triggerRef: triggerRef, + unref: unref, + useContext: useContext, + useCssModule: useCssModule, + useCssVars: useCssVars, + useSSRContext: useSSRContext, + useTransitionState: useTransitionState, + vModelText: vModelText, + vShow: vShow, + version: version, + warn: warn, + watch: watch, + watchEffect: watchEffect, + withCtx: withCtx, + withDirectives: withDirectives, + withKeys: withKeys, + withModifiers: withModifiers, + withScopeId: withScopeId +}); + +exports.Vue = Vue; +} diff --git a/packages/uni-app-vue/src/service/index.ts b/packages/uni-app-vue/src/service/index.ts index b47582aa02..5b223b363f 100644 --- a/packages/uni-app-vue/src/service/index.ts +++ b/packages/uni-app-vue/src/service/index.ts @@ -1 +1,2 @@ -export * from '../../lib/service.runtime.esm' +import * as Vue from '../../lib/service.runtime.esm' +exports.Vue = Vue diff --git a/packages/uni-cli-shared/src/json/app/pages/uniConfig.ts b/packages/uni-cli-shared/src/json/app/pages/uniConfig.ts index f75daa2a65..6275f46a8f 100644 --- a/packages/uni-cli-shared/src/json/app/pages/uniConfig.ts +++ b/packages/uni-cli-shared/src/json/app/pages/uniConfig.ts @@ -7,7 +7,7 @@ import { interface AppUniConfig { pages: string[] - window: UniApp.PagesJsonPageStyle + globalStyle: UniApp.PagesJsonPageStyle nvue: { compiler: 'uni-app' | 'weex' styleCompiler: 'weex' | 'uni-app' @@ -35,7 +35,7 @@ export function normalizeAppUniConfig( ) { const config: AppUniConfig = { pages: [], - window: pagesJson.globalStyle, + globalStyle: pagesJson.globalStyle, nvue: { compiler: getNVueCompiler(manifestJson), styleCompiler: getNVueStyleCompiler(manifestJson), diff --git a/packages/uni-core/src/helpers/bridge.ts b/packages/uni-core/src/helpers/bridge.ts index 9982b92a19..bb9f2c138b 100644 --- a/packages/uni-core/src/helpers/bridge.ts +++ b/packages/uni-core/src/helpers/bridge.ts @@ -1,13 +1,24 @@ -import { extend } from '@vue/shared' // TODO 等待 vue3 的兼容模式自带emitter import E from './TinyEmitter' export function initBridge( subscribeNamespace: 'service' | 'view' -): Partial { +): Omit { // TODO vue3 compatibility builds const emitter = new E() - return extend(emitter, { + return { + on(event: string, callback: Function) { + return emitter.on(event, callback) + }, + once(event: string, callback: Function) { + return emitter.once(event, callback) + }, + off(event: string, callback?: Function) { + return emitter.off(event, callback) + }, + emit(event: string, ...args: any[]) { + return emitter.emit(event, ...args) + }, subscribe(event: string, callback: Function, once: boolean = false): void { emitter[once ? 'once' : 'on'](`${subscribeNamespace}.${event}`, callback) }, @@ -24,5 +35,5 @@ export function initBridge( } emitter.emit(`${subscribeNamespace}.${event}`, args, pageId) }, - }) + } } diff --git a/packages/uni-core/src/service/plugin/page.ts b/packages/uni-core/src/helpers/hook.ts similarity index 63% rename from packages/uni-core/src/service/plugin/page.ts rename to packages/uni-core/src/helpers/hook.ts index 4aa7994d29..20baa75568 100644 --- a/packages/uni-core/src/service/plugin/page.ts +++ b/packages/uni-core/src/helpers/hook.ts @@ -1,47 +1,7 @@ -import { isString } from '@vue/shared' import { ComponentPublicInstance } from 'vue' +import { isString } from '@vue/shared' import { invokeArrayFns } from '@dcloudio/uni-shared' - -export function getPageById(id: number) { - return getCurrentPages().find((page) => page.$page.id === id) -} - -export function getPageVmById(id: number) { - const page = getPageById(id) - if (page) { - return (page as any).$vm as ComponentPublicInstance - } -} - -export function getCurrentPage() { - const pages = getCurrentPages() - const len = pages.length - if (len) { - return pages[len - 1] - } -} - -export function getCurrentPageMeta() { - const page = getCurrentPage() - if (page) { - return page.$page.meta - } -} - -export function getCurrentPageId() { - const meta = getCurrentPageMeta() - if (meta) { - return meta.id! - } - return -1 -} - -export function getCurrentPageVm() { - const page = getCurrentPage() - if (page) { - return (page as any).$vm as ComponentPublicInstance - } -} +import { getCurrentPageVm } from './page' export function invokeHook(name: string, args?: unknown): unknown export function invokeHook(id: number, name: string, args?: unknown): unknown diff --git a/packages/uni-core/src/helpers/index.ts b/packages/uni-core/src/helpers/index.ts index 3003fc6f3b..981c84c6e5 100644 --- a/packages/uni-core/src/helpers/index.ts +++ b/packages/uni-core/src/helpers/index.ts @@ -2,6 +2,7 @@ export * from './dom' export * from './util' export * from './icon' export * from './page' +export * from './hook' export * from './scroll' export * from './route' export * from './callbacks' diff --git a/packages/uni-core/src/helpers/page.ts b/packages/uni-core/src/helpers/page.ts index ca645cf9ff..6022b23861 100644 --- a/packages/uni-core/src/helpers/page.ts +++ b/packages/uni-core/src/helpers/page.ts @@ -16,6 +16,47 @@ export function getPageIdByVm(vm: ComponentPublicInstance) { } } +export function getPageById(id: number) { + return getCurrentPages().find((page) => page.$page.id === id) +} + +export function getPageVmById(id: number) { + const page = getPageById(id) + if (page) { + return (page as any).$vm as ComponentPublicInstance + } +} + +export function getCurrentPage() { + const pages = getCurrentPages() + const len = pages.length + if (len) { + return pages[len - 1] + } +} + +export function getCurrentPageMeta() { + const page = getCurrentPage() + if (page) { + return page.$page.meta + } +} + +export function getCurrentPageId() { + const meta = getCurrentPageMeta() + if (meta) { + return meta.id! + } + return -1 +} + +export function getCurrentPageVm() { + const page = getCurrentPage() + if (page) { + return (page as any).$vm as ComponentPublicInstance + } +} + const PAGE_META_KEYS = ['navigationBar', 'pullToRefresh'] as const function initGlobalStyle() { @@ -48,3 +89,19 @@ export function normalizePullToRefreshRpx( } return pullToRefresh } + +export function initPageInternalInstance( + url: string, + pageQuery: Record, + meta: UniApp.PageRouteMeta +): Page.PageInstance['$page'] { + const { id, route } = meta + return { + id: id!, + path: '/' + route, + route: route, + fullPath: url, + options: pageQuery, + meta, + } +} diff --git a/packages/uni-core/src/service/index.ts b/packages/uni-core/src/service/index.ts index f0352f23d7..b69ae67b74 100644 --- a/packages/uni-core/src/service/index.ts +++ b/packages/uni-core/src/service/index.ts @@ -1,2 +1,3 @@ -export * from './bridge' -export * from './plugin' +export { ServiceJSBridge } from './bridge' +export { initService } from './init' +export { initServicePlugin } from './plugin' diff --git a/packages/uni-core/src/service/init/index.ts b/packages/uni-core/src/service/init/index.ts new file mode 100644 index 0000000000..3205013516 --- /dev/null +++ b/packages/uni-core/src/service/init/index.ts @@ -0,0 +1,10 @@ +import { initOn } from './on' +import { initSubscribe } from './subscribe' + +export function initService() { + if (__NODE_JS__) { + return + } + initOn() + initSubscribe() +} diff --git a/packages/uni-core/src/service/plugin/on.ts b/packages/uni-core/src/service/init/on.ts similarity index 88% rename from packages/uni-core/src/service/plugin/on.ts rename to packages/uni-core/src/service/init/on.ts index 16e4f16e19..b7e6b021f8 100644 --- a/packages/uni-core/src/service/plugin/on.ts +++ b/packages/uni-core/src/service/init/on.ts @@ -1,5 +1,6 @@ import { ComponentPublicInstance } from '@vue/runtime-core' -import { getCurrentPage, invokeHook } from './page' +import { invokeHook } from '../../helpers/hook' +import { getCurrentPage } from '../../helpers/page' export function initOn() { UniServiceJSBridge.on('onAppEnterForeground', onAppEnterForeground) diff --git a/packages/uni-core/src/service/plugin/subscribe.ts b/packages/uni-core/src/service/init/subscribe.ts similarity index 80% rename from packages/uni-core/src/service/plugin/subscribe.ts rename to packages/uni-core/src/service/init/subscribe.ts index 59618e9f02..9adfc0b2b1 100644 --- a/packages/uni-core/src/service/plugin/subscribe.ts +++ b/packages/uni-core/src/service/init/subscribe.ts @@ -1,4 +1,5 @@ -import { getPageVmById, invokeHook } from './page' +import { getPageVmById } from '../../helpers/page' +import { invokeHook } from '../../helpers/hook' const SUBSCRIBE_LIFECYCLE_HOOKS = ['onPageScroll', 'onReachBottom'] diff --git a/packages/uni-core/src/service/plugin/index.ts b/packages/uni-core/src/service/plugin/index.ts index a2485fc50f..5079e391a2 100644 --- a/packages/uni-core/src/service/plugin/index.ts +++ b/packages/uni-core/src/service/plugin/index.ts @@ -1,14 +1,8 @@ import { App } from 'vue' import { initAppConfig } from './appConfig' -import { initOn } from './on' -import { initSubscribe } from './subscribe' -export * from './page' -export function initService(app: App) { +export function initServicePlugin(app: App) { if (__NODE_JS__) { return } - initOn() - initSubscribe() - initAppConfig(app._context.config) } diff --git a/packages/uni-core/src/view/index.ts b/packages/uni-core/src/view/index.ts index f0352f23d7..0c81f26811 100644 --- a/packages/uni-core/src/view/index.ts +++ b/packages/uni-core/src/view/index.ts @@ -1,2 +1,4 @@ -export * from './bridge' -export * from './plugin' +export { ViewJSBridge } from './bridge' +export { initView } from './init' +export { initViewPlugin } from './plugin' +export { createNativeEvent } from './plugin/componentInstance' diff --git a/packages/uni-core/src/view/init/index.ts b/packages/uni-core/src/view/init/index.ts new file mode 100644 index 0000000000..ee9200037d --- /dev/null +++ b/packages/uni-core/src/view/init/index.ts @@ -0,0 +1,14 @@ +import { initCustomDataset } from '@dcloudio/uni-shared' +import { initLongPress } from './longPress' +import { useRem } from './rem' + +export function initView() { + if (__NODE_JS__) { + return + } + useRem() + initCustomDataset() + if (__UNI_FEATURE_LONGPRESS__) { + initLongPress() + } +} diff --git a/packages/uni-core/src/view/plugin/longPress.ts b/packages/uni-core/src/view/init/longPress.ts similarity index 100% rename from packages/uni-core/src/view/plugin/longPress.ts rename to packages/uni-core/src/view/init/longPress.ts diff --git a/packages/uni-core/src/view/plugin/rem.ts b/packages/uni-core/src/view/init/rem.ts similarity index 100% rename from packages/uni-core/src/view/plugin/rem.ts rename to packages/uni-core/src/view/init/rem.ts diff --git a/packages/uni-core/src/view/plugin/index.ts b/packages/uni-core/src/view/plugin/index.ts index c6003cacb6..87dea4d232 100644 --- a/packages/uni-core/src/view/plugin/index.ts +++ b/packages/uni-core/src/view/plugin/index.ts @@ -1,21 +1,10 @@ import { App } from 'vue' - -import { initLongPress } from './longPress' import { initAppConfig } from './appConfig' -import { initCustomDataset } from '@dcloudio/uni-shared' -import { useRem } from './rem' -export function initView(app: App) { +export function initViewPlugin(app: App) { if (__NODE_JS__) { return } - useRem() - initCustomDataset() - if (__UNI_FEATURE_LONGPRESS__) { - initLongPress() - } initAppConfig(app._context.config) // TODO wxs,behaviors } - -export { createNativeEvent } from './componentInstance' diff --git a/packages/uni-h5/dist/uni-h5.cjs.js b/packages/uni-h5/dist/uni-h5.cjs.js index 4ef8f97ef1..fe648e4480 100644 --- a/packages/uni-h5/dist/uni-h5.cjs.js +++ b/packages/uni-h5/dist/uni-h5.cjs.js @@ -353,7 +353,19 @@ E.prototype = { }; function initBridge(subscribeNamespace) { const emitter = new E(); - return shared.extend(emitter, { + return { + on(event, callback) { + return emitter.on(event, callback); + }, + once(event, callback) { + return emitter.once(event, callback); + }, + off(event, callback) { + return emitter.off(event, callback); + }, + emit(event, ...args) { + return emitter.emit(event, ...args); + }, subscribe(event, callback, once = false) { emitter[once ? "once" : "on"](`${subscribeNamespace}.${event}`, callback); }, @@ -366,7 +378,7 @@ function initBridge(subscribeNamespace) { } emitter.emit(`${subscribeNamespace}.${event}`, args, pageId); } - }); + }; } const ViewJSBridge = /* @__PURE__ */ initBridge("service"); uniShared.passive(true); @@ -425,6 +437,32 @@ function createSvgIconVNode(path, color = "#000", size = 27) { function useCurrentPageId() { return vue.getCurrentInstance().root.proxy.$page.id; } +function getCurrentPage() { + const pages = getCurrentPages(); + const len = pages.length; + if (len) { + return pages[len - 1]; + } +} +function getCurrentPageMeta() { + const page = getCurrentPage(); + if (page) { + return page.$page.meta; + } +} +function getCurrentPageId() { + const meta = getCurrentPageMeta(); + if (meta) { + return meta.id; + } + return -1; +} +function getCurrentPageVm() { + const page = getCurrentPage(); + if (page) { + return page.$vm; + } +} const PAGE_META_KEYS = ["navigationBar", "pullToRefresh"]; function initGlobalStyle() { return JSON.parse(JSON.stringify(__uniConfig.globalStyle || {})); @@ -449,6 +487,36 @@ function normalizePullToRefreshRpx(pullToRefresh) { } return pullToRefresh; } +function initPageInternalInstance(url, pageQuery, meta) { + const { id, route } = meta; + return { + id, + path: "/" + route, + route, + fullPath: url, + options: pageQuery, + meta + }; +} +function invokeHook(vm, name, args) { + if (shared.isString(vm)) { + args = name; + name = vm; + vm = getCurrentPageVm(); + } else if (typeof vm === "number") { + const page = getCurrentPages().find((page2) => page2.$page.id === vm); + if (page) { + vm = page.$vm; + } else { + vm = getCurrentPageVm(); + } + } + if (!vm) { + return; + } + const hooks = vm.$[name]; + return hooks && uniShared.invokeArrayFns(hooks, args); +} function getRealRoute(fromRoute, toRoute) { if (toRoute.indexOf("/") === 0) { return toRoute; @@ -534,51 +602,6 @@ const ServiceJSBridge = /* @__PURE__ */ shared.extend(initBridge("view"), { return UniServiceJSBridge.emit("api." + name, res); } }); -function getCurrentPage() { - const pages = getCurrentPages(); - const len = pages.length; - if (len) { - return pages[len - 1]; - } -} -function getCurrentPageMeta() { - const page = getCurrentPage(); - if (page) { - return page.$page.meta; - } -} -function getCurrentPageId() { - const meta = getCurrentPageMeta(); - if (meta) { - return meta.id; - } - return -1; -} -function getCurrentPageVm() { - const page = getCurrentPage(); - if (page) { - return page.$vm; - } -} -function invokeHook(vm, name, args) { - if (shared.isString(vm)) { - args = name; - name = vm; - vm = getCurrentPageVm(); - } else if (typeof vm === "number") { - const page = getCurrentPages().find((page2) => page2.$page.id === vm); - if (page) { - vm = page.$vm; - } else { - vm = getCurrentPageVm(); - } - } - if (!vm) { - return; - } - const hooks = vm.$[name]; - return hooks && uniShared.invokeArrayFns(hooks, args); -} function converPx(value) { if (/^-?\d+[ur]px$/i.test(value)) { return value.replace(/(^-?\d+)[ur]px$/i, (text, num) => { @@ -6623,25 +6646,9 @@ function getCurrentPages$1() { function initPublicPage(route) { const meta = usePageMeta(); if (!__UNI_FEATURE_PAGES__) { - const { path: path2, alias } = __uniRoutes[0]; - return { - id: meta.id, - path: path2, - route: alias.substr(1), - fullPath: path2, - options: {}, - meta - }; + return initPageInternalInstance(__uniRoutes[0].path, {}, meta); } - const { path } = route; - return { - id: meta.id, - path, - route: route.meta.route, - fullPath: route.meta.isEntry ? route.meta.pagePath : route.fullPath, - options: {}, - meta - }; + return initPageInternalInstance(route.fullPath, {}, meta); } function initPage(vm) { const route = vm.$route; diff --git a/packages/uni-h5/dist/uni-h5.es.js b/packages/uni-h5/dist/uni-h5.es.js index ab62b40fc0..57ad5f804b 100644 --- a/packages/uni-h5/dist/uni-h5.es.js +++ b/packages/uni-h5/dist/uni-h5.es.js @@ -1,5 +1,5 @@ -import { isFunction, extend, hyphenate, isPlainObject, isString, isArray, hasOwn, isObject, capitalize, toRawType, makeMap as makeMap$1, isPromise, invokeArrayFns as invokeArrayFns$1 } from "@vue/shared"; -import { once, passive, normalizeTarget, isBuiltInComponent, initCustomDataset, invokeArrayFns, SCHEME_RE, DATA_RE, getCustomDataset, callOptions, PRIMARY_COLOR, removeLeadingSlash, getLen, debounce, NAVBAR_HEIGHT, parseQuery, ON_REACH_BOTTOM_DISTANCE, decodedQuery, WEB_INVOKE_APPSERVICE, updateElementStyle, parseUrl, addFont, scrollTo, RESPONSIVE_MIN_WIDTH, formatDateTime } from "@dcloudio/uni-shared"; +import { isFunction, extend, isString, hyphenate, isPlainObject, isArray, hasOwn, isObject, capitalize, toRawType, makeMap as makeMap$1, isPromise, invokeArrayFns as invokeArrayFns$1 } from "@vue/shared"; +import { once, passive, initCustomDataset, invokeArrayFns, normalizeTarget, isBuiltInComponent, SCHEME_RE, DATA_RE, getCustomDataset, callOptions, PRIMARY_COLOR, removeLeadingSlash, getLen, debounce, NAVBAR_HEIGHT, parseQuery, ON_REACH_BOTTOM_DISTANCE, decodedQuery, WEB_INVOKE_APPSERVICE, updateElementStyle, parseUrl, addFont, scrollTo, RESPONSIVE_MIN_WIDTH, formatDateTime } from "@dcloudio/uni-shared"; import { openBlock, createBlock, mergeProps, createVNode, toDisplayString, withModifiers, getCurrentInstance, defineComponent, ref, provide, computed, watch, onUnmounted, inject, onBeforeUnmount, reactive, onActivated, onMounted, nextTick, onBeforeMount, withDirectives, vShow, shallowRef, watchEffect, isVNode, Fragment, markRaw, createTextVNode, injectHook, onBeforeActivate, onBeforeDeactivate, renderList, onDeactivated, createApp, Transition, withCtx, KeepAlive, resolveDynamicComponent, renderSlot } from "vue"; import { initVueI18n, LOCALE_EN, LOCALE_ES, LOCALE_FR, LOCALE_ZH_HANS, LOCALE_ZH_HANT } from "@dcloudio/uni-i18n"; import { useRoute, createRouter, createWebHistory, createWebHashHistory, useRouter, isNavigationFailure, RouterView } from "vue-router"; @@ -442,7 +442,19 @@ E.prototype = { }; function initBridge(subscribeNamespace) { const emitter2 = new E(); - return extend(emitter2, { + return { + on(event, callback) { + return emitter2.on(event, callback); + }, + once(event, callback) { + return emitter2.once(event, callback); + }, + off(event, callback) { + return emitter2.off(event, callback); + }, + emit(event, ...args) { + return emitter2.emit(event, ...args); + }, subscribe(event, callback, once2 = false) { emitter2[once2 ? "once" : "on"](`${subscribeNamespace}.${event}`, callback); }, @@ -455,7 +467,7 @@ function initBridge(subscribeNamespace) { } emitter2.emit(`${subscribeNamespace}.${event}`, args, pageId); } - }); + }; } const ViewJSBridge = /* @__PURE__ */ initBridge("service"); const LONGPRESS_TIMEOUT = 350; @@ -508,6 +520,38 @@ function initLongPress() { window.addEventListener("touchend", clearLongPressTimer, passiveOptions$2); window.addEventListener("touchcancel", clearLongPressTimer, passiveOptions$2); } +function checkValue$1(value, defaultValue) { + const newValue = Number(value); + return isNaN(newValue) ? defaultValue : newValue; +} +function getWindowWidth$1() { + const screenFix = /^Apple/.test(navigator.vendor) && typeof window.orientation === "number"; + const landscape = screenFix && Math.abs(window.orientation) === 90; + var screenWidth = screenFix ? Math[landscape ? "max" : "min"](screen.width, screen.height) : screen.width; + var windowWidth = Math.min(window.innerWidth, document.documentElement.clientWidth, screenWidth) || screenWidth; + return windowWidth; +} +function useRem() { + function updateRem() { + const config = __uniConfig.globalStyle || {}; + const maxWidth = checkValue$1(config.rpxCalcMaxDeviceWidth, 960); + const baseWidth = checkValue$1(config.rpxCalcBaseDeviceWidth, 375); + let width = getWindowWidth$1(); + width = width <= maxWidth ? width : baseWidth; + document.documentElement.style.fontSize = width / 23.4375 + "px"; + } + updateRem(); + document.addEventListener("DOMContentLoaded", updateRem); + window.addEventListener("load", updateRem); + window.addEventListener("resize", updateRem); +} +function initView() { + useRem(); + initCustomDataset(); + if (__UNI_FEATURE_LONGPRESS__) { + initLongPress(); + } +} var attrs = ["top", "left", "right", "bottom"]; var inited$1; var elementComputedStyle = {}; @@ -812,6 +856,41 @@ function getPageIdByVm(vm) { return rootProxy.$page.id; } } +function getPageById(id2) { + return getCurrentPages().find((page) => page.$page.id === id2); +} +function getPageVmById(id2) { + const page = getPageById(id2); + if (page) { + return page.$vm; + } +} +function getCurrentPage() { + const pages = getCurrentPages(); + const len = pages.length; + if (len) { + return pages[len - 1]; + } +} +function getCurrentPageMeta() { + const page = getCurrentPage(); + if (page) { + return page.$page.meta; + } +} +function getCurrentPageId() { + const meta = getCurrentPageMeta(); + if (meta) { + return meta.id; + } + return -1; +} +function getCurrentPageVm() { + const page = getCurrentPage(); + if (page) { + return page.$vm; + } +} const PAGE_META_KEYS = ["navigationBar", "pullToRefresh"]; function initGlobalStyle() { return JSON.parse(JSON.stringify(__uniConfig.globalStyle || {})); @@ -836,6 +915,36 @@ function normalizePullToRefreshRpx(pullToRefresh) { } return pullToRefresh; } +function initPageInternalInstance(url, pageQuery, meta) { + const { id: id2, route } = meta; + return { + id: id2, + path: "/" + route, + route, + fullPath: url, + options: pageQuery, + meta + }; +} +function invokeHook(vm, name, args) { + if (isString(vm)) { + args = name; + name = vm; + vm = getCurrentPageVm(); + } else if (typeof vm === "number") { + const page = getCurrentPages().find((page2) => page2.$page.id === vm); + if (page) { + vm = page.$vm; + } else { + vm = getCurrentPageVm(); + } + } + if (!vm) { + return; + } + const hooks = vm.$[name]; + return hooks && invokeArrayFns(hooks, args); +} function disableScrollListener(evt) { evt.preventDefault(); } @@ -1217,37 +1326,7 @@ function initAppConfig$1(appConfig) { globalProperties.$gcd = getComponentDescriptor; } } -function checkValue$1(value, defaultValue) { - const newValue = Number(value); - return isNaN(newValue) ? defaultValue : newValue; -} -function getWindowWidth$1() { - const screenFix = /^Apple/.test(navigator.vendor) && typeof window.orientation === "number"; - const landscape = screenFix && Math.abs(window.orientation) === 90; - var screenWidth = screenFix ? Math[landscape ? "max" : "min"](screen.width, screen.height) : screen.width; - var windowWidth = Math.min(window.innerWidth, document.documentElement.clientWidth, screenWidth) || screenWidth; - return windowWidth; -} -function useRem() { - function updateRem() { - const config = __uniConfig.globalStyle || {}; - const maxWidth = checkValue$1(config.rpxCalcMaxDeviceWidth, 960); - const baseWidth = checkValue$1(config.rpxCalcBaseDeviceWidth, 375); - let width = getWindowWidth$1(); - width = width <= maxWidth ? width : baseWidth; - document.documentElement.style.fontSize = width / 23.4375 + "px"; - } - updateRem(); - document.addEventListener("DOMContentLoaded", updateRem); - window.addEventListener("load", updateRem); - window.addEventListener("resize", updateRem); -} -function initView(app) { - useRem(); - initCustomDataset(); - if (__UNI_FEATURE_LONGPRESS__) { - initLongPress(); - } +function initViewPlugin(app) { initAppConfig$1(app._context.config); } const ServiceJSBridge = /* @__PURE__ */ extend(initBridge("view"), { @@ -1255,6 +1334,43 @@ const ServiceJSBridge = /* @__PURE__ */ extend(initBridge("view"), { return UniServiceJSBridge.emit("api." + name, res); } }); +function initOn() { + UniServiceJSBridge.on("onAppEnterForeground", onAppEnterForeground); + UniServiceJSBridge.on("onAppEnterBackground", onAppEnterBackground); +} +function onAppEnterForeground() { + const page = getCurrentPage(); + const showOptions = { + path: "", + query: {} + }; + if (page) { + showOptions.path = page.$page.route; + showOptions.query = page.$page.options; + } + invokeHook(getApp(), "onShow", showOptions); + invokeHook(page, "onShow"); +} +function onAppEnterBackground() { + invokeHook(getApp(), "onHide"); + invokeHook(getCurrentPage(), "onHide"); +} +const SUBSCRIBE_LIFECYCLE_HOOKS = ["onPageScroll", "onReachBottom"]; +function initSubscribe() { + SUBSCRIBE_LIFECYCLE_HOOKS.forEach((name) => UniServiceJSBridge.subscribe(name, createPageEvent(name))); +} +function createPageEvent(name) { + return (args, pageId) => { + const vm = getPageVmById(pageId); + if (vm) { + invokeHook(vm, name, args); + } + }; +} +function initService() { + initOn(); + initSubscribe(); +} function querySelector(vm, selector) { const el = vm.$el.querySelector(selector); return el && el.__vue__; @@ -1296,96 +1412,7 @@ function initAppConfig(appConfig) { extend(globalProperties, wxInstance); } } -function getPageById(id2) { - return getCurrentPages().find((page) => page.$page.id === id2); -} -function getPageVmById(id2) { - const page = getPageById(id2); - if (page) { - return page.$vm; - } -} -function getCurrentPage() { - const pages = getCurrentPages(); - const len = pages.length; - if (len) { - return pages[len - 1]; - } -} -function getCurrentPageMeta() { - const page = getCurrentPage(); - if (page) { - return page.$page.meta; - } -} -function getCurrentPageId() { - const meta = getCurrentPageMeta(); - if (meta) { - return meta.id; - } - return -1; -} -function getCurrentPageVm() { - const page = getCurrentPage(); - if (page) { - return page.$vm; - } -} -function invokeHook(vm, name, args) { - if (isString(vm)) { - args = name; - name = vm; - vm = getCurrentPageVm(); - } else if (typeof vm === "number") { - const page = getCurrentPages().find((page2) => page2.$page.id === vm); - if (page) { - vm = page.$vm; - } else { - vm = getCurrentPageVm(); - } - } - if (!vm) { - return; - } - const hooks = vm.$[name]; - return hooks && invokeArrayFns(hooks, args); -} -function initOn() { - UniServiceJSBridge.on("onAppEnterForeground", onAppEnterForeground); - UniServiceJSBridge.on("onAppEnterBackground", onAppEnterBackground); -} -function onAppEnterForeground() { - const page = getCurrentPage(); - const showOptions = { - path: "", - query: {} - }; - if (page) { - showOptions.path = page.$page.route; - showOptions.query = page.$page.options; - } - invokeHook(getApp(), "onShow", showOptions); - invokeHook(page, "onShow"); -} -function onAppEnterBackground() { - invokeHook(getApp(), "onHide"); - invokeHook(getCurrentPage(), "onHide"); -} -const SUBSCRIBE_LIFECYCLE_HOOKS = ["onPageScroll", "onReachBottom"]; -function initSubscribe() { - SUBSCRIBE_LIFECYCLE_HOOKS.forEach((name) => UniServiceJSBridge.subscribe(name, createPageEvent(name))); -} -function createPageEvent(name) { - return (args, pageId) => { - const vm = getPageVmById(pageId); - if (vm) { - invokeHook(vm, name, args); - } - }; -} -function initService(app) { - initOn(); - initSubscribe(); +function initServicePlugin(app) { initAppConfig(app._context.config); } function converPx(value) { @@ -13180,25 +13207,9 @@ function createPageState(type, __id__) { function initPublicPage(route) { const meta = usePageMeta(); if (!__UNI_FEATURE_PAGES__) { - const { path: path2, alias } = __uniRoutes[0]; - return { - id: meta.id, - path: path2, - route: alias.substr(1), - fullPath: path2, - options: {}, - meta - }; + return initPageInternalInstance(__uniRoutes[0].path, {}, meta); } - const { path } = route; - return { - id: meta.id, - path, - route: route.meta.route, - fullPath: route.meta.isEntry ? route.meta.pagePath : route.fullPath, - options: {}, - meta - }; + return initPageInternalInstance(route.fullPath, {}, meta); } function initPage(vm) { const route = vm.$route; @@ -13381,8 +13392,8 @@ function initHistory() { var index$9 = { install(app) { initApp$1(app); - initView(app); - initService(app); + initViewPlugin(app); + initServicePlugin(app); if (__UNI_FEATURE_PAGES__) { initRouter(app); } @@ -13396,6 +13407,8 @@ function initApp(vm) { appVm = vm; appVm.$vm = vm; appVm.globalData = appVm.$options.globalData || {}; + initService(); + initView(); } function wrapperComponentSetup(comp, { init: init2, setup, before }) { before && before(comp); diff --git a/packages/uni-h5/src/framework/plugin/index.ts b/packages/uni-h5/src/framework/plugin/index.ts index fe358146ff..55a6961d0e 100644 --- a/packages/uni-h5/src/framework/plugin/index.ts +++ b/packages/uni-h5/src/framework/plugin/index.ts @@ -1,15 +1,15 @@ import { App } from 'vue' import { initApp } from '@dcloudio/uni-vue' -import { initView, initService } from '@dcloudio/uni-core' +import { initViewPlugin, initServicePlugin } from '@dcloudio/uni-core' import { initRouter } from './router' export default { install(app: App) { initApp(app) - initView(app) - initService(app) + initViewPlugin(app) + initServicePlugin(app) if (__UNI_FEATURE_PAGES__) { initRouter(app) diff --git a/packages/uni-h5/src/framework/setup/app.ts b/packages/uni-h5/src/framework/setup/app.ts index bcf8bcf313..217775d593 100644 --- a/packages/uni-h5/src/framework/setup/app.ts +++ b/packages/uni-h5/src/framework/setup/app.ts @@ -1,4 +1,5 @@ import { ComponentPublicInstance } from 'vue' +import { initService, initView } from '@dcloudio/uni-core' let appVm: ComponentPublicInstance @@ -10,4 +11,6 @@ export function initApp(vm: ComponentPublicInstance) { appVm = vm appVm.$vm = vm appVm.globalData = appVm.$options.globalData || {} + initService() + initView() } diff --git a/packages/uni-h5/src/framework/setup/page.ts b/packages/uni-h5/src/framework/setup/page.ts index 352f7342c1..7195d39590 100644 --- a/packages/uni-h5/src/framework/setup/page.ts +++ b/packages/uni-h5/src/framework/setup/page.ts @@ -12,6 +12,7 @@ import { disableScrollListener, createScrollListener, CreateScrollListenerOptions, + initPageInternalInstance, } from '@dcloudio/uni-core' import { ON_REACH_BOTTOM_DISTANCE } from '@dcloudio/uni-shared' import { usePageMeta } from './provide' @@ -21,7 +22,7 @@ import { getStateId } from '../../helpers/dom' const SEP = '$$' -const currentPagesMap = new Map() +const currentPagesMap = new Map() function pruneCurrentPages() { currentPagesMap.forEach((page, id) => { @@ -36,11 +37,11 @@ export function getCurrentPagesMap() { } export function getCurrentPages() { - const curPages: Page.PageInstance[] = [] + const curPages: ComponentPublicInstance[] = [] const pages = currentPagesMap.values() for (const page of pages) { - if ((page as ComponentPublicInstance).__isTabBar) { - if ((page as ComponentPublicInstance).$.__isActive) { + if (page.__isTabBar) { + if (page.$.__isActive) { curPages.push(page) } } else { @@ -78,25 +79,9 @@ export function createPageState(type: NavigateType, __id__?: number) { function initPublicPage(route: RouteLocationNormalizedLoaded) { const meta = usePageMeta() if (!__UNI_FEATURE_PAGES__) { - const { path, alias } = __uniRoutes[0] - return { - id: meta.id, - path, - route: alias!.substr(1), - fullPath: path, - options: {}, - meta, - } - } - const { path } = route - return { - id: meta.id, - path: path, - route: route.meta.route, - fullPath: route.meta.isEntry ? route.meta.pagePath : route.fullPath, - options: {}, // $route.query - meta, + return initPageInternalInstance(__uniRoutes[0].path, {}, meta) } + return initPageInternalInstance(route.fullPath, {}, meta) } export function initPage(vm: ComponentPublicInstance) { @@ -105,10 +90,7 @@ export function initPage(vm: ComponentPublicInstance) { ;(vm as any).$vm = vm ;(vm as any).$page = page vm.__isTabBar = page.meta.isTabBar! - currentPagesMap.set( - normalizeRouteKey(page.path, page.id), - vm as unknown as Page.PageInstance - ) + currentPagesMap.set(normalizeRouteKey(page.path, page.id), vm) } export function normalizeRouteKey(path: string, id: number) { @@ -185,7 +167,7 @@ function pruneRouteCache(key: string) { } function updateCurPageAttrs(pageMeta: UniApp.PageRouteMeta) { - const nvueDirKey = 'nvue-dir-' + __uniConfig.nvue['flex-direction'] + const nvueDirKey = 'nvue-dir-' + __uniConfig.nvue!['flex-direction'] if (pageMeta.isNVue) { document.body.setAttribute('nvue', '') document.body.setAttribute(nvueDirKey, '') diff --git a/packages/uni-h5/src/service/api/media/preview-image.js b/packages/uni-h5/src/service/api/media/preview-image.js deleted file mode 100644 index 384a941103..0000000000 --- a/packages/uni-h5/src/service/api/media/preview-image.js +++ /dev/null @@ -1,24 +0,0 @@ -export function previewImage({ urls, current }, callbackId) { - const { invokeCallbackHandler: invoke } = UniServiceJSBridge - - getApp().$router.push( - { - type: 'navigateTo', - path: '/preview-image', - params: { - urls, - current - } - }, - function() { - invoke(callbackId, { - errMsg: 'previewImage:ok' - }) - }, - function() { - invoke(callbackId, { - errMsg: 'previewImage:fail' - }) - } - ) -} diff --git a/packages/uni-shared/dist/uni-shared.cjs.js b/packages/uni-shared/dist/uni-shared.cjs.js index f09d5072bd..5f1f817dfb 100644 --- a/packages/uni-shared/dist/uni-shared.cjs.js +++ b/packages/uni-shared/dist/uni-shared.cjs.js @@ -217,7 +217,7 @@ function parseUrl(url) { const [path, querystring] = url.split('?', 2); return { path, - query: parseQuery(querystring), + query: parseQuery(querystring || ''), }; } diff --git a/packages/uni-shared/dist/uni-shared.es.js b/packages/uni-shared/dist/uni-shared.es.js index 3ac7ba30d0..63a0bd78cc 100644 --- a/packages/uni-shared/dist/uni-shared.es.js +++ b/packages/uni-shared/dist/uni-shared.es.js @@ -213,7 +213,7 @@ function parseUrl(url) { const [path, querystring] = url.split('?', 2); return { path, - query: parseQuery(querystring), + query: parseQuery(querystring || ''), }; } diff --git a/packages/uni-shared/src/url.ts b/packages/uni-shared/src/url.ts index bbea8ce1aa..7bf649e84a 100644 --- a/packages/uni-shared/src/url.ts +++ b/packages/uni-shared/src/url.ts @@ -4,6 +4,6 @@ export function parseUrl(url: string) { const [path, querystring] = url.split('?', 2) return { path, - query: parseQuery(querystring), + query: parseQuery(querystring || ''), } } -- GitLab