diff --git a/packages/uni-mp-alipay/dist/uni.api.esm.js b/packages/uni-mp-alipay/dist/uni.api.esm.js index 4a03871d4d1dce1491dd79bcefbfbe5172d16ddf..ba03f1560f15258a47e267829c5aae6f15652408 100644 --- a/packages/uni-mp-alipay/dist/uni.api.esm.js +++ b/packages/uni-mp-alipay/dist/uni.api.esm.js @@ -1,5 +1,41 @@ import { isArray, hasOwn, isString, isPlainObject, isObject, capitalize, toRawType, makeMap, isPromise, isFunction, extend } from '@vue/shared'; +const eventChannels = {}; +const eventChannelStack = []; +let id = 0; +function initEventChannel(events, cache = true) { + id++; + const eventChannel = new my.EventChannel(id, events); + if (cache) { + eventChannels[id] = eventChannel; + eventChannelStack.push(eventChannel); + } + return eventChannel; +} +function getEventChannel(id) { + if (id) { + const eventChannel = eventChannels[id]; + delete eventChannels[id]; + return eventChannel; + } + return eventChannelStack.shift(); +} +const navigateTo = { + args(fromArgs) { + const id = initEventChannel(fromArgs.events).id; + if (fromArgs.url) { + fromArgs.url = + fromArgs.url + + (fromArgs.url.indexOf('?') === -1 ? '?' : '&') + + '__id__=' + + id; + } + }, + returnValue(fromRes) { + fromRes.eventChannel = getEventChannel(); + }, +}; + function getBaseSystemInfo() { return my.getSystemInfoSync() } @@ -623,7 +659,8 @@ function addSafeAreaInsets(fromRes, toRes) { bottom: fromRes.windowHeight - safeArea.bottom, }; } -} +} + const redirectTo = {}; const getProvider = initGetProvider({ @@ -1212,7 +1249,8 @@ var protocols = /*#__PURE__*/Object.freeze({ saveImageToPhotosAlbum: saveImageToPhotosAlbum, saveVideoToPhotosAlbum: saveVideoToPhotosAlbum, chooseAddress: chooseAddress, - redirectTo: redirectTo + redirectTo: redirectTo, + navigateTo: navigateTo }); var index = initUni(shims, protocols); diff --git a/packages/uni-mp-alipay/dist/uni.mp.esm.js b/packages/uni-mp-alipay/dist/uni.mp.esm.js index d9040424526814afd1a33d491dfd2e17b674fdc2..aa7c7317f83f43be4288362e6708cd00d526a30d 100644 --- a/packages/uni-mp-alipay/dist/uni.mp.esm.js +++ b/packages/uni-mp-alipay/dist/uni.mp.esm.js @@ -1,4 +1,125 @@ -import { hasOwn, isArray, toNumber, isPlainObject, isObject, capitalize, isFunction, extend, NOOP, EMPTY_OBJ, camelize } from '@vue/shared'; +import { isPlainObject, hasOwn, isArray, toNumber, isObject, capitalize, isFunction, extend, NOOP, EMPTY_OBJ, camelize } from '@vue/shared'; + +const encode = encodeURIComponent; +function stringifyQuery(obj, encodeStr = encode) { + const res = obj + ? Object.keys(obj) + .map((key) => { + let val = obj[key]; + if (typeof val === undefined || val === null) { + val = ''; + } + else if (isPlainObject(val)) { + val = JSON.stringify(val); + } + return encodeStr(key) + '=' + encodeStr(val); + }) + .filter((x) => x.length > 0) + .join('&') + : null; + return res ? `?${res}` : ''; +} +const invokeArrayFns = (fns, arg) => { + let ret; + for (let i = 0; i < fns.length; i++) { + ret = fns[i](arg); + } + return ret; +}; +// lifecycle +// App and Page +const ON_SHOW = 'onShow'; +const ON_HIDE = 'onHide'; +//App +const ON_LAUNCH = 'onLaunch'; +const ON_ERROR = 'onError'; +const ON_THEME_CHANGE = 'onThemeChange'; +const ON_PAGE_NOT_FOUND = 'onPageNotFound'; +const ON_UNHANDLE_REJECTION = 'onUnhandledRejection'; +//Page +const ON_LOAD = 'onLoad'; +const ON_READY = 'onReady'; +const ON_UNLOAD = 'onUnload'; +const ON_RESIZE = 'onResize'; +const ON_BACK_PRESS = 'onBackPress'; +const ON_TAB_ITEM_TAP = 'onTabItemTap'; +const ON_REACH_BOTTOM = 'onReachBottom'; +const ON_PULL_DOWN_REFRESH = 'onPullDownRefresh'; +const ON_ADD_TO_FAVORITES = 'onAddToFavorites'; + +class EventChannel { + constructor(id, events) { + this.id = id; + this.listener = {}; + this.emitCache = {}; + if (events) { + Object.keys(events).forEach((name) => { + this.on(name, events[name]); + }); + } + } + emit(eventName, ...args) { + const fns = this.listener[eventName]; + if (!fns) { + return (this.emitCache[eventName] || (this.emitCache[eventName] = [])).push(args); + } + fns.forEach((opt) => { + opt.fn.apply(opt.fn, args); + }); + this.listener[eventName] = fns.filter((opt) => opt.type !== 'once'); + } + on(eventName, fn) { + this._addListener(eventName, 'on', fn); + this._clearCache(eventName); + } + once(eventName, fn) { + this._addListener(eventName, 'once', fn); + this._clearCache(eventName); + } + off(eventName, fn) { + const fns = this.listener[eventName]; + if (!fns) { + return; + } + if (fn) { + for (let i = 0; i < fns.length;) { + if (fns[i].fn === fn) { + fns.splice(i, 1); + i--; + } + i++; + } + } + else { + delete this.listener[eventName]; + } + } + _clearCache(eventName) { + const cacheArgs = this.emitCache[eventName]; + if (cacheArgs) { + for (; cacheArgs.length > 0;) { + this.emit.apply(this, [eventName, ...cacheArgs.shift()]); + } + } + } + _addListener(eventName, type, fn) { + (this.listener[eventName] || (this.listener[eventName] = [])).push({ + fn, + type, + }); + } +} + +const eventChannels = {}; +const eventChannelStack = []; +function getEventChannel(id) { + if (id) { + const eventChannel = eventChannels[id]; + delete eventChannels[id]; + return eventChannel; + } + return eventChannelStack.shift(); +} function setModel(target, key, value, modifiers) { if (isArray(modifiers)) { @@ -88,6 +209,14 @@ function initBaseInstance(instance, options) { }, }); } + ctx.getOpenerEventChannel = function () { + if (!this.__eventChannel__) { + this.__eventChannel__ = new EventChannel(); + } + return this.__eventChannel__; + }; + ctx.$hasHook = hasHook; + ctx.$callHook = callHook; // $emit instance.emit = createEmitFn(instance.emit, ctx); } @@ -120,47 +249,22 @@ function initMocks(instance, mpInstance, mocks) { ctx[mock] = mpInstance[mock]; } }); -} - -const encode = encodeURIComponent; -function stringifyQuery(obj, encodeStr = encode) { - const res = obj - ? Object.keys(obj) - .map((key) => { - let val = obj[key]; - if (typeof val === undefined || val === null) { - val = ''; - } - else if (isPlainObject(val)) { - val = JSON.stringify(val); - } - return encodeStr(key) + '=' + encodeStr(val); - }) - .filter((x) => x.length > 0) - .join('&') - : null; - return res ? `?${res}` : ''; } -// lifecycle -// App and Page -const ON_SHOW = 'onShow'; -const ON_HIDE = 'onHide'; -//App -const ON_LAUNCH = 'onLaunch'; -const ON_ERROR = 'onError'; -const ON_THEME_CHANGE = 'onThemeChange'; -const ON_PAGE_NOT_FOUND = 'onPageNotFound'; -const ON_UNHANDLE_REJECTION = 'onUnhandledRejection'; -//Page -const ON_LOAD = 'onLoad'; -const ON_READY = 'onReady'; -const ON_UNLOAD = 'onUnload'; -const ON_RESIZE = 'onResize'; -const ON_BACK_PRESS = 'onBackPress'; -const ON_TAB_ITEM_TAP = 'onTabItemTap'; -const ON_REACH_BOTTOM = 'onReachBottom'; -const ON_PULL_DOWN_REFRESH = 'onPullDownRefresh'; -const ON_ADD_TO_FAVORITES = 'onAddToFavorites'; +function hasHook(name) { + const hooks = this.$[name]; + if (hooks && hooks.length) { + return true; + } + return false; +} +function callHook(name, args) { + if (name === 'onLoad' && args && args.__id__) { + this.__eventChannel__ = getEventChannel(args.__id__); + delete args.__id__; + } + const hooks = this.$[name]; + return hooks && invokeArrayFns(hooks, args); +} const PAGE_HOOKS = [ ON_LOAD, @@ -282,7 +386,7 @@ function initWxsCallMethods(methods, wxsCallMethods) { }); } function findVmByVueId(instance, vuePid) { - // TODO vue3 中 没有 $children + // 标准 vue3 中 没有 $children,定制了内核 const $children = instance.$children; // 优先查找直属(反向查找:https://github.com/dcloudio/uni-app/issues/1200) for (let i = $children.length - 1; i >= 0; i--) { @@ -757,8 +861,8 @@ function parse(appOptions) { } var parseAppOptions = /*#__PURE__*/Object.freeze({ - __proto__: null, - parse: parse + __proto__: null, + parse: parse }); function handleLink$1(event) { @@ -1128,6 +1232,7 @@ function createComponent$1(vueOptions) { } const createApp = initCreateApp(parseAppOptions); +my.EventChannel = EventChannel; my.createApp = createApp; my.createPage = createPage; my.createComponent = createComponent; diff --git a/packages/uni-mp-alipay/src/api/protocols.ts b/packages/uni-mp-alipay/src/api/protocols.ts index 763541de86e84d11103f0103a15609356e592856..618ffd9a2416b7a2d3addd41b0e7674bf6bafbf4 100644 --- a/packages/uni-mp-alipay/src/api/protocols.ts +++ b/packages/uni-mp-alipay/src/api/protocols.ts @@ -2,7 +2,7 @@ import { isPlainObject, isArray } from '@vue/shared' import { addSafeAreaInsets } from '@dcloudio/uni-mp-core' -export { redirectTo } from '@dcloudio/uni-mp-core' +export { redirectTo, navigateTo } from '@dcloudio/uni-mp-core' function handleNetworkInfo( fromRes: my.IGetNetworkTypeSuccessResult, @@ -202,7 +202,7 @@ export const compressImage = { }, returnValue( fromRes: my.ICompressImageSuccessResult, - toRes: UniApp.CompressImageSuccessData + toRes: UniApp.CompressVideoSuccessData ) { const apFilePaths = fromRes.apFilePaths if (apFilePaths && apFilePaths.length) { @@ -234,7 +234,7 @@ export const previewImage = { const currentIndex = Number(fromArgs.current) if (isNaN(currentIndex)) { if (fromArgs.current && isArray(fromArgs.urls)) { - const index = fromArgs.urls.indexOf(fromArgs.current) + const index = fromArgs.urls.indexOf(fromArgs.current as string) toArgs.current = ~index ? index : 0 } } else { diff --git a/packages/uni-mp-alipay/src/runtime/index.ts b/packages/uni-mp-alipay/src/runtime/index.ts index 8e3faf62ffa2de1ba372087a4b59874c78aa7028..14205bd5d55c30eb8bd31d874ba0ca1b4e0bdb7d 100644 --- a/packages/uni-mp-alipay/src/runtime/index.ts +++ b/packages/uni-mp-alipay/src/runtime/index.ts @@ -1,3 +1,5 @@ +import { EventChannel } from '@dcloudio/uni-shared' + import { initCreateApp } from '@dcloudio/uni-mp-core' import * as parseAppOptions from './parseAppOptions' @@ -6,6 +8,7 @@ export { createPage } from './createPage' export { createComponent } from './createComponent' export const createApp = initCreateApp(parseAppOptions) +;(my as any).EventChannel = EventChannel ;(my as any).createApp = createApp ;(my as any).createPage = createPage ;(my as any).createComponent = createComponent diff --git a/packages/uni-mp-baidu/dist/uni.api.esm.js b/packages/uni-mp-baidu/dist/uni.api.esm.js index 77c97d4d591fb49c4ad98b7b0946bdcfcccf0b2e..42fd4dbe9766bf695f088b85f5d62e001c641464 100644 --- a/packages/uni-mp-baidu/dist/uni.api.esm.js +++ b/packages/uni-mp-baidu/dist/uni.api.esm.js @@ -1,5 +1,41 @@ import { isArray, hasOwn, isString, isPlainObject, isObject, capitalize, toRawType, makeMap, isPromise, isFunction, extend } from '@vue/shared'; +const eventChannels = {}; +const eventChannelStack = []; +let id = 0; +function initEventChannel(events, cache = true) { + id++; + const eventChannel = new swan.EventChannel(id, events); + if (cache) { + eventChannels[id] = eventChannel; + eventChannelStack.push(eventChannel); + } + return eventChannel; +} +function getEventChannel(id) { + if (id) { + const eventChannel = eventChannels[id]; + delete eventChannels[id]; + return eventChannel; + } + return eventChannelStack.shift(); +} +const navigateTo = { + args(fromArgs) { + const id = initEventChannel(fromArgs.events).id; + if (fromArgs.url) { + fromArgs.url = + fromArgs.url + + (fromArgs.url.indexOf('?') === -1 ? '?' : '&') + + '__id__=' + + id; + } + }, + returnValue(fromRes) { + fromRes.eventChannel = getEventChannel(); + }, +}; + function getBaseSystemInfo() { return swan.getSystemInfoSync() } @@ -613,6 +649,26 @@ function initGetProvider(providers) { }; } +function addSafeAreaInsets(fromRes, toRes) { + if (fromRes.safeArea) { + const safeArea = fromRes.safeArea; + toRes.safeAreaInsets = { + top: safeArea.top, + left: safeArea.left, + right: fromRes.windowWidth - safeArea.right, + bottom: fromRes.windowHeight - safeArea.bottom, + }; + } +} + +const getSystemInfo = { + returnValue: addSafeAreaInsets, +}; + +const getSystemInfoSync = getSystemInfo; + +const redirectTo = {}; + const previewImage = { args(fromArgs, toArgs) { let currentIndex = parseInt(fromArgs.current); @@ -645,23 +701,7 @@ const previewImage = { loop: false, }; }, -}; -function addSafeAreaInsets(fromRes, toRes) { - if (fromRes.safeArea) { - const safeArea = fromRes.safeArea; - toRes.safeAreaInsets = { - top: safeArea.top, - left: safeArea.left, - right: fromRes.windowWidth - safeArea.right, - bottom: fromRes.windowHeight - safeArea.bottom, - }; - } -} -const getSystemInfo = { - returnValue: addSafeAreaInsets, -}; -const getSystemInfoSync = getSystemInfo; -const redirectTo = {}; +}; const getProvider = initGetProvider({ oauth: ['baidu'], @@ -777,6 +817,7 @@ var protocols = /*#__PURE__*/Object.freeze({ showShareMenu: showShareMenu, getAccountInfoSync: getAccountInfoSync, redirectTo: redirectTo, + navigateTo: navigateTo, previewImage: previewImage, getSystemInfo: getSystemInfo, getSystemInfoSync: getSystemInfoSync diff --git a/packages/uni-mp-baidu/dist/uni.mp.esm.js b/packages/uni-mp-baidu/dist/uni.mp.esm.js index e55bfeacc324d40c36c63d8f3afae7395876d3eb..ef517c2d999ad7767b7291eb6702f7fd7e4343e7 100644 --- a/packages/uni-mp-baidu/dist/uni.mp.esm.js +++ b/packages/uni-mp-baidu/dist/uni.mp.esm.js @@ -1,4 +1,124 @@ -import { isArray, hasOwn, toNumber, isPlainObject, isObject, isFunction, extend, NOOP, camelize } from '@vue/shared'; +import { isPlainObject, isArray, hasOwn, toNumber, isObject, isFunction, extend, NOOP, camelize } from '@vue/shared'; + +const encode = encodeURIComponent; +function stringifyQuery(obj, encodeStr = encode) { + const res = obj + ? Object.keys(obj) + .map((key) => { + let val = obj[key]; + if (typeof val === undefined || val === null) { + val = ''; + } + else if (isPlainObject(val)) { + val = JSON.stringify(val); + } + return encodeStr(key) + '=' + encodeStr(val); + }) + .filter((x) => x.length > 0) + .join('&') + : null; + return res ? `?${res}` : ''; +} +const invokeArrayFns = (fns, arg) => { + let ret; + for (let i = 0; i < fns.length; i++) { + ret = fns[i](arg); + } + return ret; +}; +// lifecycle +// App and Page +const ON_SHOW = 'onShow'; +const ON_HIDE = 'onHide'; +//App +const ON_LAUNCH = 'onLaunch'; +const ON_ERROR = 'onError'; +const ON_THEME_CHANGE = 'onThemeChange'; +const ON_PAGE_NOT_FOUND = 'onPageNotFound'; +const ON_UNHANDLE_REJECTION = 'onUnhandledRejection'; +//Page +const ON_LOAD = 'onLoad'; +const ON_READY = 'onReady'; +const ON_UNLOAD = 'onUnload'; +const ON_RESIZE = 'onResize'; +const ON_TAB_ITEM_TAP = 'onTabItemTap'; +const ON_REACH_BOTTOM = 'onReachBottom'; +const ON_PULL_DOWN_REFRESH = 'onPullDownRefresh'; +const ON_ADD_TO_FAVORITES = 'onAddToFavorites'; + +class EventChannel { + constructor(id, events) { + this.id = id; + this.listener = {}; + this.emitCache = {}; + if (events) { + Object.keys(events).forEach((name) => { + this.on(name, events[name]); + }); + } + } + emit(eventName, ...args) { + const fns = this.listener[eventName]; + if (!fns) { + return (this.emitCache[eventName] || (this.emitCache[eventName] = [])).push(args); + } + fns.forEach((opt) => { + opt.fn.apply(opt.fn, args); + }); + this.listener[eventName] = fns.filter((opt) => opt.type !== 'once'); + } + on(eventName, fn) { + this._addListener(eventName, 'on', fn); + this._clearCache(eventName); + } + once(eventName, fn) { + this._addListener(eventName, 'once', fn); + this._clearCache(eventName); + } + off(eventName, fn) { + const fns = this.listener[eventName]; + if (!fns) { + return; + } + if (fn) { + for (let i = 0; i < fns.length;) { + if (fns[i].fn === fn) { + fns.splice(i, 1); + i--; + } + i++; + } + } + else { + delete this.listener[eventName]; + } + } + _clearCache(eventName) { + const cacheArgs = this.emitCache[eventName]; + if (cacheArgs) { + for (; cacheArgs.length > 0;) { + this.emit.apply(this, [eventName, ...cacheArgs.shift()]); + } + } + } + _addListener(eventName, type, fn) { + (this.listener[eventName] || (this.listener[eventName] = [])).push({ + fn, + type, + }); + } +} + +const eventChannels = {}; +const eventChannelStack = []; +function getEventChannel(id) { + if (id) { + const eventChannel = eventChannels[id]; + delete eventChannels[id]; + return eventChannel; + } + return eventChannelStack.shift(); +} function setModel(target, key, value, modifiers) { if (isArray(modifiers)) { @@ -82,6 +202,14 @@ function initBaseInstance(instance, options) { }); } } + ctx.getOpenerEventChannel = function () { + if (!this.__eventChannel__) { + this.__eventChannel__ = new EventChannel(); + } + return this.__eventChannel__; + }; + ctx.$hasHook = hasHook; + ctx.$callHook = callHook; // $emit instance.emit = createEmitFn(instance.emit, ctx); } @@ -111,46 +239,22 @@ function initMocks(instance, mpInstance, mocks) { ctx[mock] = mpInstance[mock]; } }); -} - -const encode = encodeURIComponent; -function stringifyQuery(obj, encodeStr = encode) { - const res = obj - ? Object.keys(obj) - .map((key) => { - let val = obj[key]; - if (typeof val === undefined || val === null) { - val = ''; - } - else if (isPlainObject(val)) { - val = JSON.stringify(val); - } - return encodeStr(key) + '=' + encodeStr(val); - }) - .filter((x) => x.length > 0) - .join('&') - : null; - return res ? `?${res}` : ''; } -// lifecycle -// App and Page -const ON_SHOW = 'onShow'; -const ON_HIDE = 'onHide'; -//App -const ON_LAUNCH = 'onLaunch'; -const ON_ERROR = 'onError'; -const ON_THEME_CHANGE = 'onThemeChange'; -const ON_PAGE_NOT_FOUND = 'onPageNotFound'; -const ON_UNHANDLE_REJECTION = 'onUnhandledRejection'; -//Page -const ON_LOAD = 'onLoad'; -const ON_READY = 'onReady'; -const ON_UNLOAD = 'onUnload'; -const ON_RESIZE = 'onResize'; -const ON_TAB_ITEM_TAP = 'onTabItemTap'; -const ON_REACH_BOTTOM = 'onReachBottom'; -const ON_PULL_DOWN_REFRESH = 'onPullDownRefresh'; -const ON_ADD_TO_FAVORITES = 'onAddToFavorites'; +function hasHook(name) { + const hooks = this.$[name]; + if (hooks && hooks.length) { + return true; + } + return false; +} +function callHook(name, args) { + if (name === 'onLoad' && args && args.__id__) { + this.__eventChannel__ = getEventChannel(args.__id__); + delete args.__id__; + } + const hooks = this.$[name]; + return hooks && invokeArrayFns(hooks, args); +} const PAGE_HOOKS = [ ON_LOAD, @@ -304,7 +408,7 @@ function initRefs(instance, mpInstance) { }); } function findVmByVueId(instance, vuePid) { - // TODO vue3 中 没有 $children + // 标准 vue3 中 没有 $children,定制了内核 const $children = instance.$children; // 优先查找直属(反向查找:https://github.com/dcloudio/uni-app/issues/1200) for (let i = $children.length - 1; i >= 0; i--) { @@ -882,8 +986,8 @@ function parse$2(appOptions) { } var parseAppOptions = /*#__PURE__*/Object.freeze({ - __proto__: null, - parse: parse$2 + __proto__: null, + parse: parse$2 }); function initLifetimes({ mocks, isPage, initRelation, vueOptions, }) { @@ -988,13 +1092,13 @@ function parse$1(componentOptions) { } var parseComponentOptions = /*#__PURE__*/Object.freeze({ - __proto__: null, - mocks: mocks, - isPage: isPage, - initRelation: initRelation, - parse: parse$1, - handleLink: handleLink, - initLifetimes: initLifetimes + __proto__: null, + mocks: mocks, + isPage: isPage, + initRelation: initRelation, + parse: parse$1, + handleLink: handleLink, + initLifetimes: initLifetimes }); function parse(pageOptions) { @@ -1020,18 +1124,19 @@ function parse(pageOptions) { } var parsePageOptions = /*#__PURE__*/Object.freeze({ - __proto__: null, - parse: parse, - handleLink: handleLink, - initLifetimes: initLifetimes, - mocks: mocks, - isPage: isPage, - initRelation: initRelation + __proto__: null, + parse: parse, + handleLink: handleLink, + initLifetimes: initLifetimes, + mocks: mocks, + isPage: isPage, + initRelation: initRelation }); const createApp = initCreateApp(parseAppOptions); const createPage = initCreatePage(parsePageOptions); const createComponent = initCreateComponent(parseComponentOptions); +swan.EventChannel = EventChannel; swan.createApp = createApp; swan.createPage = createPage; swan.createComponent = createComponent; diff --git a/packages/uni-mp-baidu/src/api/protocols.ts b/packages/uni-mp-baidu/src/api/protocols.ts index 9d6aecf9b52ad5e4aeb139d962e8989da7f30466..daec15f83cb1bfdff51008950f30c5409e3644ea 100644 --- a/packages/uni-mp-baidu/src/api/protocols.ts +++ b/packages/uni-mp-baidu/src/api/protocols.ts @@ -1,5 +1,6 @@ export { redirectTo, + navigateTo, previewImage, getSystemInfo, getSystemInfoSync, diff --git a/packages/uni-mp-baidu/src/runtime/index.ts b/packages/uni-mp-baidu/src/runtime/index.ts index 7fbcafc543892f1ad7a1849a436980061c2aba4d..51173c7736be819ff650eb946b6312e59b991828 100644 --- a/packages/uni-mp-baidu/src/runtime/index.ts +++ b/packages/uni-mp-baidu/src/runtime/index.ts @@ -1,3 +1,4 @@ +import { EventChannel } from '@dcloudio/uni-shared' import { initCreateApp, initCreatePage, @@ -13,6 +14,7 @@ import * as parseComponentOptions from './parseComponentOptions' export const createApp = initCreateApp(parseAppOptions) export const createPage = initCreatePage(parsePageOptions) export const createComponent = initCreateComponent(parseComponentOptions) +;(swan as any).EventChannel = EventChannel ;(swan as any).createApp = createApp ;(swan as any).createPage = createPage ;(swan as any).createComponent = createComponent diff --git a/packages/uni-mp-core/src/api/index.ts b/packages/uni-mp-core/src/api/index.ts index 2a74ebb8e3b03facc9866fcc8dc9e1d772efdd6d..8e69add5ffe66688ac717a9931b84eaab655f9e3 100644 --- a/packages/uni-mp-core/src/api/index.ts +++ b/packages/uni-mp-core/src/api/index.ts @@ -1,5 +1,5 @@ import { hasOwn } from '@vue/shared' - +// 直接引用具体文件,避免引入其他需要额外配置的信息,比如@dcloudio/uni-platform import { upx2px } from '@dcloudio/uni-api/src/service/base/upx2px' import { addInterceptor, diff --git a/packages/uni-mp-core/src/api/protocols.ts b/packages/uni-mp-core/src/api/protocols.ts deleted file mode 100644 index 09c0f3a27e24dc2fd20a8ce5739c0845ac1b462d..0000000000000000000000000000000000000000 --- a/packages/uni-mp-core/src/api/protocols.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { isArray } from '@vue/shared' - -export type MPProtocolArgsValue = { - name?: string - value: any -} -type MPProtocolArgsValueObject = boolean | string | MPProtocolArgsValue -type MPProtocolArgsValueFunction = ( - val: any, - fromArgs: any, - toArgs: any -) => MPProtocolArgsValueObject -type MPProtocolArgsObject = { - [key: string]: MPProtocolArgsValueObject | MPProtocolArgsValueFunction -} -type MPProtocolArgsFunction = ( - fromArgs: T, - toArgs: T -) => MPProtocolArgsObject | void - -export type MPProtocolArgs = MPProtocolArgsObject | MPProtocolArgsFunction - -type MPProtocolReturnValue = MPProtocolArgs -export type MPProtocolObject = { - name?: string - args?: MPProtocolArgs - returnValue?: MPProtocolReturnValue -} -type MPProtocolFunction = (arg: unknown) => MPProtocolObject -type MPProtocol = MPProtocolObject | MPProtocolFunction - -type MPProtocolsBase = { - [key: string]: MPProtocol -} - -type MPProdocolsReturnValue = { - returnValue?: ( - methodName: string, - res: Record - ) => Record -} - -export type MPProtocols = MPProtocolsBase | MPProdocolsReturnValue - -export const previewImage: MPProtocol = { - args( - fromArgs: UniApp.PreviewImageOptions, - toArgs: WechatMiniprogram.PreviewImageOption - ) { - let currentIndex = parseInt(fromArgs.current as string) - if (isNaN(currentIndex)) { - return - } - const urls = fromArgs.urls - if (!isArray(urls)) { - return - } - const len = urls.length - if (!len) { - return - } - if (currentIndex < 0) { - currentIndex = 0 - } else if (currentIndex >= len) { - currentIndex = len - 1 - } - if (currentIndex > 0) { - toArgs.current = urls[currentIndex] - toArgs.urls = urls.filter((item, index) => - index < currentIndex ? item !== urls[currentIndex] : true - ) - } else { - toArgs.current = urls[0] - } - return { - indicator: false, - loop: false, - } - }, -} - -export function addSafeAreaInsets( - fromRes: any, - toRes: UniApp.GetSystemInfoResult -) { - if (fromRes.safeArea) { - const safeArea = fromRes.safeArea - toRes.safeAreaInsets = { - top: safeArea.top, - left: safeArea.left, - right: fromRes.windowWidth - safeArea.right, - bottom: fromRes.windowHeight - safeArea.bottom, - } - } -} - -export const getSystemInfo = { - returnValue: addSafeAreaInsets, -} - -export const getSystemInfoSync = getSystemInfo - -export const redirectTo = {} diff --git a/packages/uni-mp-core/src/api/protocols/addSafeAreaInsets.ts b/packages/uni-mp-core/src/api/protocols/addSafeAreaInsets.ts new file mode 100644 index 0000000000000000000000000000000000000000..9024eff10853b92ddd557651a222a263b3e7ac50 --- /dev/null +++ b/packages/uni-mp-core/src/api/protocols/addSafeAreaInsets.ts @@ -0,0 +1,14 @@ +export function addSafeAreaInsets( + fromRes: any, + toRes: UniApp.GetSystemInfoResult +) { + if (fromRes.safeArea) { + const safeArea = fromRes.safeArea + toRes.safeAreaInsets = { + top: safeArea.top, + left: safeArea.left, + right: fromRes.windowWidth - safeArea.right, + bottom: fromRes.windowHeight - safeArea.bottom, + } + } +} diff --git a/packages/uni-mp-core/src/api/protocols/getSystemInfo.ts b/packages/uni-mp-core/src/api/protocols/getSystemInfo.ts new file mode 100644 index 0000000000000000000000000000000000000000..fc8cb388434841785e509824da13a16931de626a --- /dev/null +++ b/packages/uni-mp-core/src/api/protocols/getSystemInfo.ts @@ -0,0 +1,6 @@ +import { addSafeAreaInsets } from './addSafeAreaInsets' +import { MPProtocol } from './types' + +export const getSystemInfo: MPProtocol = { + returnValue: addSafeAreaInsets, +} diff --git a/packages/uni-mp-core/src/api/protocols/getSystemInfoSync.ts b/packages/uni-mp-core/src/api/protocols/getSystemInfoSync.ts new file mode 100644 index 0000000000000000000000000000000000000000..03e194f69f3aa570318f31a07a662e63c253c3b9 --- /dev/null +++ b/packages/uni-mp-core/src/api/protocols/getSystemInfoSync.ts @@ -0,0 +1,3 @@ +import { getSystemInfo } from './getSystemInfo' + +export const getSystemInfoSync = getSystemInfo diff --git a/packages/uni-mp-core/src/api/protocols/index.ts b/packages/uni-mp-core/src/api/protocols/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..27acb91c74228c80f55e6a0ba54547bac445cb11 --- /dev/null +++ b/packages/uni-mp-core/src/api/protocols/index.ts @@ -0,0 +1,7 @@ +export { addSafeAreaInsets } from './addSafeAreaInsets' +export { getSystemInfo } from './getSystemInfo' +export { getSystemInfoSync } from './getSystemInfoSync' +export { redirectTo } from './redirectTo' +export { previewImage } from './previewImage' +export { navigateTo, initEventChannel, getEventChannel } from './navigateTo' +export * from './types' diff --git a/packages/uni-mp-core/src/api/protocols/navigateTo.ts b/packages/uni-mp-core/src/api/protocols/navigateTo.ts new file mode 100644 index 0000000000000000000000000000000000000000..469cc887f600f925025daa43dad9a644f3b4f696 --- /dev/null +++ b/packages/uni-mp-core/src/api/protocols/navigateTo.ts @@ -0,0 +1,46 @@ +import type { EventChannel } from '@dcloudio/uni-shared' +import { MPProtocol } from './types' + +const eventChannels: Record = {} + +const eventChannelStack: EventChannel[] = [] + +let id = 0 + +export function initEventChannel( + events: Record void>, + cache = true +) { + id++ + const eventChannel = new __GLOBAL__.EventChannel(id, events) + if (cache) { + eventChannels[id] = eventChannel + eventChannelStack.push(eventChannel) + } + return eventChannel +} + +export function getEventChannel(id?: number) { + if (id) { + const eventChannel = eventChannels[id] + delete eventChannels[id] + return eventChannel + } + return eventChannelStack.shift() +} + +export const navigateTo: MPProtocol = { + args(fromArgs) { + const id = initEventChannel(fromArgs.events).id + if (fromArgs.url) { + fromArgs.url = + fromArgs.url + + (fromArgs.url.indexOf('?') === -1 ? '?' : '&') + + '__id__=' + + id + } + }, + returnValue(fromRes) { + fromRes.eventChannel = getEventChannel() + }, +} diff --git a/packages/uni-mp-core/src/api/protocols/previewImage.ts b/packages/uni-mp-core/src/api/protocols/previewImage.ts new file mode 100644 index 0000000000000000000000000000000000000000..76b51d660091c8c7bba30d2fa9fe42b5571e11da --- /dev/null +++ b/packages/uni-mp-core/src/api/protocols/previewImage.ts @@ -0,0 +1,39 @@ +import { isArray } from '@vue/shared' +import { MPProtocol } from './types' + +export const previewImage: MPProtocol = { + args( + fromArgs: UniApp.PreviewImageOptions, + toArgs: WechatMiniprogram.PreviewImageOption + ) { + let currentIndex = parseInt(fromArgs.current as string) + if (isNaN(currentIndex)) { + return + } + const urls = fromArgs.urls + if (!isArray(urls)) { + return + } + const len = urls.length + if (!len) { + return + } + if (currentIndex < 0) { + currentIndex = 0 + } else if (currentIndex >= len) { + currentIndex = len - 1 + } + if (currentIndex > 0) { + toArgs.current = urls[currentIndex] + toArgs.urls = urls.filter((item, index) => + index < currentIndex ? item !== urls[currentIndex] : true + ) + } else { + toArgs.current = urls[0] + } + return { + indicator: false, + loop: false, + } + }, +} diff --git a/packages/uni-mp-core/src/api/protocols/redirectTo.ts b/packages/uni-mp-core/src/api/protocols/redirectTo.ts new file mode 100644 index 0000000000000000000000000000000000000000..9b3b421914c7f0a5d7e892d155ab8e66a18382ea --- /dev/null +++ b/packages/uni-mp-core/src/api/protocols/redirectTo.ts @@ -0,0 +1 @@ +export const redirectTo = {} diff --git a/packages/uni-mp-core/src/api/protocols/types.ts b/packages/uni-mp-core/src/api/protocols/types.ts new file mode 100644 index 0000000000000000000000000000000000000000..583ee22d357863b5884c64dc59766f9f52aed35f --- /dev/null +++ b/packages/uni-mp-core/src/api/protocols/types.ts @@ -0,0 +1,41 @@ +export type MPProtocolArgsValue = { + name?: string + value: any +} +type MPProtocolArgsValueObject = boolean | string | MPProtocolArgsValue +type MPProtocolArgsValueFunction = ( + val: any, + fromArgs: any, + toArgs: any +) => MPProtocolArgsValueObject +type MPProtocolArgsObject = { + [key: string]: MPProtocolArgsValueObject | MPProtocolArgsValueFunction +} +type MPProtocolArgsFunction = ( + fromArgs: T, + toArgs: T +) => MPProtocolArgsObject | void + +export type MPProtocolArgs = MPProtocolArgsObject | MPProtocolArgsFunction + +type MPProtocolReturnValue = MPProtocolArgs +export type MPProtocolObject = { + name?: string + args?: MPProtocolArgs + returnValue?: MPProtocolReturnValue +} +type MPProtocolFunction = (arg: unknown) => MPProtocolObject +export type MPProtocol = MPProtocolObject | MPProtocolFunction + +type MPProtocolsBase = { + [key: string]: MPProtocol +} + +type MPProdocolsReturnValue = { + returnValue?: ( + methodName: string, + res: Record + ) => Record +} + +export type MPProtocols = MPProtocolsBase | MPProdocolsReturnValue diff --git a/packages/uni-mp-core/src/index.ts b/packages/uni-mp-core/src/index.ts index b8d5c7665d77b2cbc092e369f91186cf25a8c8f8..aa9098e8912a69efc3911ce38aab28366220da98 100644 --- a/packages/uni-mp-core/src/index.ts +++ b/packages/uni-mp-core/src/index.ts @@ -35,6 +35,7 @@ export { // protocols export { redirectTo, + navigateTo, previewImage, getSystemInfo, getSystemInfoSync, diff --git a/packages/uni-mp-core/src/runtime/componentInstance.ts b/packages/uni-mp-core/src/runtime/componentInstance.ts index 56b70ed39a30be0a7818f8f4c920b4eaa76037ee..fb8601484a2b78873250b8ca5cc7c41a76999e71 100644 --- a/packages/uni-mp-core/src/runtime/componentInstance.ts +++ b/packages/uni-mp-core/src/runtime/componentInstance.ts @@ -1,3 +1,4 @@ +import { EventChannel, invokeArrayFns } from '@dcloudio/uni-shared' import { capitalize, hasOwn, @@ -8,6 +9,7 @@ import { } from '@vue/shared' import { ComponentPublicInstance, ComponentInternalInstance } from 'vue' +import { getEventChannel } from '../api/protocols/navigateTo' import { MPComponentInstance } from '../index' function setModel( @@ -141,6 +143,20 @@ export function initBaseInstance( } } + ctx.getOpenerEventChannel = function () { + // 微信小程序使用自身getOpenerEventChannel + if (__PLATFORM__ === 'mp-weixin') { + return options.mpInstance.getOpenerEventChannel() + } + if (!this.__eventChannel__) { + this.__eventChannel__ = new EventChannel() + } + return this.__eventChannel__ + } + + ctx.$hasHook = hasHook + ctx.$callHook = callHook + // $emit instance.emit = createEmitFn(instance.emit, ctx) } @@ -185,3 +201,20 @@ export function initMocks( } }) } + +function hasHook(this: ComponentPublicInstance, name: string) { + const hooks = (this.$ as any)[name] + if (hooks && hooks.length) { + return true + } + return false +} + +function callHook(this: ComponentPublicInstance, name: string, args?: unknown) { + if (name === 'onLoad' && args && (args as any).__id__) { + ;(this as any).__eventChannel__ = getEventChannel((args as any).__id__) + delete (args as any).__id__ + } + const hooks = (this.$ as any)[name] + return hooks && invokeArrayFns(hooks, args) +} diff --git a/packages/uni-mp-core/src/runtime/util.ts b/packages/uni-mp-core/src/runtime/util.ts index 03c8a508b9aa1f0f1f03fb135559e42fb9f8081a..a0be9f2f9141d2030dac11234d3127f21bc3add8 100644 --- a/packages/uni-mp-core/src/runtime/util.ts +++ b/packages/uni-mp-core/src/runtime/util.ts @@ -85,7 +85,7 @@ export function findVmByVueId( instance: ComponentPublicInstance, vuePid: string ): ComponentPublicInstance | undefined { - // TODO vue3 中 没有 $children + // 标准 vue3 中 没有 $children,定制了内核 const $children = (instance as any).$children // 优先查找直属(反向查找:https://github.com/dcloudio/uni-app/issues/1200) for (let i = $children.length - 1; i >= 0; i--) { diff --git a/packages/uni-mp-qq/dist/uni.api.esm.js b/packages/uni-mp-qq/dist/uni.api.esm.js index 8f1aa8c4bc426d0e5464f436b37a4b79e5433f92..7d52fe0a0b158c515c0668da760d2de491dfbb67 100644 --- a/packages/uni-mp-qq/dist/uni.api.esm.js +++ b/packages/uni-mp-qq/dist/uni.api.esm.js @@ -1,5 +1,41 @@ import { isArray, hasOwn, isString, isPlainObject, isObject, capitalize, toRawType, makeMap, isPromise, isFunction, extend } from '@vue/shared'; +const eventChannels = {}; +const eventChannelStack = []; +let id = 0; +function initEventChannel(events, cache = true) { + id++; + const eventChannel = new qq.EventChannel(id, events); + if (cache) { + eventChannels[id] = eventChannel; + eventChannelStack.push(eventChannel); + } + return eventChannel; +} +function getEventChannel(id) { + if (id) { + const eventChannel = eventChannels[id]; + delete eventChannels[id]; + return eventChannel; + } + return eventChannelStack.shift(); +} +const navigateTo = { + args(fromArgs) { + const id = initEventChannel(fromArgs.events).id; + if (fromArgs.url) { + fromArgs.url = + fromArgs.url + + (fromArgs.url.indexOf('?') === -1 ? '?' : '&') + + '__id__=' + + id; + } + }, + returnValue(fromRes) { + fromRes.eventChannel = getEventChannel(); + }, +}; + function getBaseSystemInfo() { return qq.getSystemInfoSync() } @@ -613,6 +649,26 @@ function initGetProvider(providers) { }; } +function addSafeAreaInsets(fromRes, toRes) { + if (fromRes.safeArea) { + const safeArea = fromRes.safeArea; + toRes.safeAreaInsets = { + top: safeArea.top, + left: safeArea.left, + right: fromRes.windowWidth - safeArea.right, + bottom: fromRes.windowHeight - safeArea.bottom, + }; + } +} + +const getSystemInfo = { + returnValue: addSafeAreaInsets, +}; + +const getSystemInfoSync = getSystemInfo; + +const redirectTo = {}; + const previewImage = { args(fromArgs, toArgs) { let currentIndex = parseInt(fromArgs.current); @@ -645,23 +701,7 @@ const previewImage = { loop: false, }; }, -}; -function addSafeAreaInsets(fromRes, toRes) { - if (fromRes.safeArea) { - const safeArea = fromRes.safeArea; - toRes.safeAreaInsets = { - top: safeArea.top, - left: safeArea.left, - right: fromRes.windowWidth - safeArea.right, - bottom: fromRes.windowHeight - safeArea.bottom, - }; - } -} -const getSystemInfo = { - returnValue: addSafeAreaInsets, -}; -const getSystemInfoSync = getSystemInfo; -const redirectTo = {}; +}; const getProvider = initGetProvider({ oauth: ['qq'], @@ -678,6 +718,7 @@ var shims = /*#__PURE__*/Object.freeze({ var protocols = /*#__PURE__*/Object.freeze({ __proto__: null, redirectTo: redirectTo, + navigateTo: navigateTo, previewImage: previewImage, getSystemInfo: getSystemInfo, getSystemInfoSync: getSystemInfoSync diff --git a/packages/uni-mp-qq/dist/uni.mp.esm.js b/packages/uni-mp-qq/dist/uni.mp.esm.js index 0aedc0664ca2fcb2116d4f07afa0568849d4303a..ec0e18d956263dc2f762318432a0c7c9c0af52aa 100644 --- a/packages/uni-mp-qq/dist/uni.mp.esm.js +++ b/packages/uni-mp-qq/dist/uni.mp.esm.js @@ -1,4 +1,124 @@ -import { isArray, hasOwn, toNumber, isPlainObject, isObject, isFunction, extend, NOOP, camelize } from '@vue/shared'; +import { isPlainObject, isArray, hasOwn, toNumber, isObject, isFunction, extend, NOOP, camelize } from '@vue/shared'; + +const encode = encodeURIComponent; +function stringifyQuery(obj, encodeStr = encode) { + const res = obj + ? Object.keys(obj) + .map((key) => { + let val = obj[key]; + if (typeof val === undefined || val === null) { + val = ''; + } + else if (isPlainObject(val)) { + val = JSON.stringify(val); + } + return encodeStr(key) + '=' + encodeStr(val); + }) + .filter((x) => x.length > 0) + .join('&') + : null; + return res ? `?${res}` : ''; +} +const invokeArrayFns = (fns, arg) => { + let ret; + for (let i = 0; i < fns.length; i++) { + ret = fns[i](arg); + } + return ret; +}; +// lifecycle +// App and Page +const ON_SHOW = 'onShow'; +const ON_HIDE = 'onHide'; +//App +const ON_LAUNCH = 'onLaunch'; +const ON_ERROR = 'onError'; +const ON_THEME_CHANGE = 'onThemeChange'; +const ON_PAGE_NOT_FOUND = 'onPageNotFound'; +const ON_UNHANDLE_REJECTION = 'onUnhandledRejection'; +//Page +const ON_LOAD = 'onLoad'; +const ON_READY = 'onReady'; +const ON_UNLOAD = 'onUnload'; +const ON_RESIZE = 'onResize'; +const ON_TAB_ITEM_TAP = 'onTabItemTap'; +const ON_REACH_BOTTOM = 'onReachBottom'; +const ON_PULL_DOWN_REFRESH = 'onPullDownRefresh'; +const ON_ADD_TO_FAVORITES = 'onAddToFavorites'; + +class EventChannel { + constructor(id, events) { + this.id = id; + this.listener = {}; + this.emitCache = {}; + if (events) { + Object.keys(events).forEach((name) => { + this.on(name, events[name]); + }); + } + } + emit(eventName, ...args) { + const fns = this.listener[eventName]; + if (!fns) { + return (this.emitCache[eventName] || (this.emitCache[eventName] = [])).push(args); + } + fns.forEach((opt) => { + opt.fn.apply(opt.fn, args); + }); + this.listener[eventName] = fns.filter((opt) => opt.type !== 'once'); + } + on(eventName, fn) { + this._addListener(eventName, 'on', fn); + this._clearCache(eventName); + } + once(eventName, fn) { + this._addListener(eventName, 'once', fn); + this._clearCache(eventName); + } + off(eventName, fn) { + const fns = this.listener[eventName]; + if (!fns) { + return; + } + if (fn) { + for (let i = 0; i < fns.length;) { + if (fns[i].fn === fn) { + fns.splice(i, 1); + i--; + } + i++; + } + } + else { + delete this.listener[eventName]; + } + } + _clearCache(eventName) { + const cacheArgs = this.emitCache[eventName]; + if (cacheArgs) { + for (; cacheArgs.length > 0;) { + this.emit.apply(this, [eventName, ...cacheArgs.shift()]); + } + } + } + _addListener(eventName, type, fn) { + (this.listener[eventName] || (this.listener[eventName] = [])).push({ + fn, + type, + }); + } +} + +const eventChannels = {}; +const eventChannelStack = []; +function getEventChannel(id) { + if (id) { + const eventChannel = eventChannels[id]; + delete eventChannels[id]; + return eventChannel; + } + return eventChannelStack.shift(); +} function setModel(target, key, value, modifiers) { if (isArray(modifiers)) { @@ -82,6 +202,14 @@ function initBaseInstance(instance, options) { }); } } + ctx.getOpenerEventChannel = function () { + if (!this.__eventChannel__) { + this.__eventChannel__ = new EventChannel(); + } + return this.__eventChannel__; + }; + ctx.$hasHook = hasHook; + ctx.$callHook = callHook; // $emit instance.emit = createEmitFn(instance.emit, ctx); } @@ -111,46 +239,22 @@ function initMocks(instance, mpInstance, mocks) { ctx[mock] = mpInstance[mock]; } }); -} - -const encode = encodeURIComponent; -function stringifyQuery(obj, encodeStr = encode) { - const res = obj - ? Object.keys(obj) - .map((key) => { - let val = obj[key]; - if (typeof val === undefined || val === null) { - val = ''; - } - else if (isPlainObject(val)) { - val = JSON.stringify(val); - } - return encodeStr(key) + '=' + encodeStr(val); - }) - .filter((x) => x.length > 0) - .join('&') - : null; - return res ? `?${res}` : ''; } -// lifecycle -// App and Page -const ON_SHOW = 'onShow'; -const ON_HIDE = 'onHide'; -//App -const ON_LAUNCH = 'onLaunch'; -const ON_ERROR = 'onError'; -const ON_THEME_CHANGE = 'onThemeChange'; -const ON_PAGE_NOT_FOUND = 'onPageNotFound'; -const ON_UNHANDLE_REJECTION = 'onUnhandledRejection'; -//Page -const ON_LOAD = 'onLoad'; -const ON_READY = 'onReady'; -const ON_UNLOAD = 'onUnload'; -const ON_RESIZE = 'onResize'; -const ON_TAB_ITEM_TAP = 'onTabItemTap'; -const ON_REACH_BOTTOM = 'onReachBottom'; -const ON_PULL_DOWN_REFRESH = 'onPullDownRefresh'; -const ON_ADD_TO_FAVORITES = 'onAddToFavorites'; +function hasHook(name) { + const hooks = this.$[name]; + if (hooks && hooks.length) { + return true; + } + return false; +} +function callHook(name, args) { + if (name === 'onLoad' && args && args.__id__) { + this.__eventChannel__ = getEventChannel(args.__id__); + delete args.__id__; + } + const hooks = this.$[name]; + return hooks && invokeArrayFns(hooks, args); +} const PAGE_HOOKS = [ ON_LOAD, @@ -304,7 +408,7 @@ function initRefs(instance, mpInstance) { }); } function findVmByVueId(instance, vuePid) { - // TODO vue3 中 没有 $children + // 标准 vue3 中 没有 $children,定制了内核 const $children = instance.$children; // 优先查找直属(反向查找:https://github.com/dcloudio/uni-app/issues/1200) for (let i = $children.length - 1; i >= 0; i--) { @@ -916,12 +1020,12 @@ function handleLink(event) { } var parseOptions = /*#__PURE__*/Object.freeze({ - __proto__: null, - mocks: mocks, - isPage: isPage, - initRelation: initRelation, - handleLink: handleLink, - initLifetimes: initLifetimes + __proto__: null, + mocks: mocks, + isPage: isPage, + initRelation: initRelation, + handleLink: handleLink, + initLifetimes: initLifetimes }); const createApp = initCreateApp(); @@ -931,6 +1035,7 @@ wx.createApp = createApp; wx.createPage = createPage; wx.createComponent = createComponent; +qq.EventChannel = EventChannel; qq.createApp = createApp; qq.createPage = createPage; qq.createComponent = createComponent; diff --git a/packages/uni-mp-qq/src/api/protocols.ts b/packages/uni-mp-qq/src/api/protocols.ts index fdbeb102291695af6b390a6cb97999e009643c41..0a42f0fbdbb535be49242a869d0448bb2361d88e 100644 --- a/packages/uni-mp-qq/src/api/protocols.ts +++ b/packages/uni-mp-qq/src/api/protocols.ts @@ -1,5 +1,6 @@ export { redirectTo, + navigateTo, previewImage, getSystemInfo, getSystemInfoSync, diff --git a/packages/uni-mp-qq/src/runtime/index.ts b/packages/uni-mp-qq/src/runtime/index.ts index dc5885a603a98997c2bab51e7bf8e915128f37c9..fc8b0c4b914eb270e7204a4258a209c214b726d9 100644 --- a/packages/uni-mp-qq/src/runtime/index.ts +++ b/packages/uni-mp-qq/src/runtime/index.ts @@ -1,9 +1,12 @@ +import { EventChannel } from '@dcloudio/uni-shared' import { createApp, createPage, createComponent, } from '@dcloudio/uni-mp-weixin/src/runtime' + export * from '@dcloudio/uni-mp-weixin/src/runtime' +;(qq as any).EventChannel = EventChannel ;(qq as any).createApp = createApp ;(qq as any).createPage = createPage ;(qq as any).createComponent = createComponent diff --git a/packages/uni-mp-toutiao/dist/uni.api.esm.js b/packages/uni-mp-toutiao/dist/uni.api.esm.js index bca8402843dca10810e362e157571eb530570134..10618b2a12486f8268425bb704945499daea76f0 100644 --- a/packages/uni-mp-toutiao/dist/uni.api.esm.js +++ b/packages/uni-mp-toutiao/dist/uni.api.esm.js @@ -1,5 +1,41 @@ import { isArray, hasOwn, isString, isPlainObject, isObject, capitalize, toRawType, makeMap, isPromise, isFunction, extend } from '@vue/shared'; +const eventChannels = {}; +const eventChannelStack = []; +let id = 0; +function initEventChannel(events, cache = true) { + id++; + const eventChannel = new tt.EventChannel(id, events); + if (cache) { + eventChannels[id] = eventChannel; + eventChannelStack.push(eventChannel); + } + return eventChannel; +} +function getEventChannel(id) { + if (id) { + const eventChannel = eventChannels[id]; + delete eventChannels[id]; + return eventChannel; + } + return eventChannelStack.shift(); +} +const navigateTo = { + args(fromArgs) { + const id = initEventChannel(fromArgs.events).id; + if (fromArgs.url) { + fromArgs.url = + fromArgs.url + + (fromArgs.url.indexOf('?') === -1 ? '?' : '&') + + '__id__=' + + id; + } + }, + returnValue(fromRes) { + fromRes.eventChannel = getEventChannel(); + }, +}; + function getBaseSystemInfo() { return tt.getSystemInfoSync() } @@ -613,6 +649,8 @@ function initGetProvider(providers) { }; } +const redirectTo = {}; + const previewImage = { args(fromArgs, toArgs) { let currentIndex = parseInt(fromArgs.current); @@ -645,8 +683,7 @@ const previewImage = { loop: false, }; }, -}; -const redirectTo = {}; +}; const getProvider = initGetProvider({ oauth: ['toutiao'], @@ -748,6 +785,7 @@ var protocols = /*#__PURE__*/Object.freeze({ requestPayment: requestPayment, getFileInfo: getFileInfo, redirectTo: redirectTo, + navigateTo: navigateTo, previewImage: previewImage }); diff --git a/packages/uni-mp-toutiao/dist/uni.mp.esm.js b/packages/uni-mp-toutiao/dist/uni.mp.esm.js index 0151ba2a8111c77292089626ec4401e5873e95b8..912f6bfca61e860b3bddae50517f4f69fd74c43c 100644 --- a/packages/uni-mp-toutiao/dist/uni.mp.esm.js +++ b/packages/uni-mp-toutiao/dist/uni.mp.esm.js @@ -1,4 +1,124 @@ -import { isArray, hasOwn, toNumber, isPlainObject, isObject, isFunction, extend, NOOP, camelize } from '@vue/shared'; +import { isPlainObject, isArray, hasOwn, toNumber, isObject, isFunction, extend, NOOP, camelize } from '@vue/shared'; + +const encode = encodeURIComponent; +function stringifyQuery(obj, encodeStr = encode) { + const res = obj + ? Object.keys(obj) + .map((key) => { + let val = obj[key]; + if (typeof val === undefined || val === null) { + val = ''; + } + else if (isPlainObject(val)) { + val = JSON.stringify(val); + } + return encodeStr(key) + '=' + encodeStr(val); + }) + .filter((x) => x.length > 0) + .join('&') + : null; + return res ? `?${res}` : ''; +} +const invokeArrayFns = (fns, arg) => { + let ret; + for (let i = 0; i < fns.length; i++) { + ret = fns[i](arg); + } + return ret; +}; +// lifecycle +// App and Page +const ON_SHOW = 'onShow'; +const ON_HIDE = 'onHide'; +//App +const ON_LAUNCH = 'onLaunch'; +const ON_ERROR = 'onError'; +const ON_THEME_CHANGE = 'onThemeChange'; +const ON_PAGE_NOT_FOUND = 'onPageNotFound'; +const ON_UNHANDLE_REJECTION = 'onUnhandledRejection'; +//Page +const ON_LOAD = 'onLoad'; +const ON_READY = 'onReady'; +const ON_UNLOAD = 'onUnload'; +const ON_RESIZE = 'onResize'; +const ON_TAB_ITEM_TAP = 'onTabItemTap'; +const ON_REACH_BOTTOM = 'onReachBottom'; +const ON_PULL_DOWN_REFRESH = 'onPullDownRefresh'; +const ON_ADD_TO_FAVORITES = 'onAddToFavorites'; + +class EventChannel { + constructor(id, events) { + this.id = id; + this.listener = {}; + this.emitCache = {}; + if (events) { + Object.keys(events).forEach((name) => { + this.on(name, events[name]); + }); + } + } + emit(eventName, ...args) { + const fns = this.listener[eventName]; + if (!fns) { + return (this.emitCache[eventName] || (this.emitCache[eventName] = [])).push(args); + } + fns.forEach((opt) => { + opt.fn.apply(opt.fn, args); + }); + this.listener[eventName] = fns.filter((opt) => opt.type !== 'once'); + } + on(eventName, fn) { + this._addListener(eventName, 'on', fn); + this._clearCache(eventName); + } + once(eventName, fn) { + this._addListener(eventName, 'once', fn); + this._clearCache(eventName); + } + off(eventName, fn) { + const fns = this.listener[eventName]; + if (!fns) { + return; + } + if (fn) { + for (let i = 0; i < fns.length;) { + if (fns[i].fn === fn) { + fns.splice(i, 1); + i--; + } + i++; + } + } + else { + delete this.listener[eventName]; + } + } + _clearCache(eventName) { + const cacheArgs = this.emitCache[eventName]; + if (cacheArgs) { + for (; cacheArgs.length > 0;) { + this.emit.apply(this, [eventName, ...cacheArgs.shift()]); + } + } + } + _addListener(eventName, type, fn) { + (this.listener[eventName] || (this.listener[eventName] = [])).push({ + fn, + type, + }); + } +} + +const eventChannels = {}; +const eventChannelStack = []; +function getEventChannel(id) { + if (id) { + const eventChannel = eventChannels[id]; + delete eventChannels[id]; + return eventChannel; + } + return eventChannelStack.shift(); +} function setModel(target, key, value, modifiers) { if (isArray(modifiers)) { @@ -82,6 +202,14 @@ function initBaseInstance(instance, options) { }); } } + ctx.getOpenerEventChannel = function () { + if (!this.__eventChannel__) { + this.__eventChannel__ = new EventChannel(); + } + return this.__eventChannel__; + }; + ctx.$hasHook = hasHook; + ctx.$callHook = callHook; // $emit instance.emit = createEmitFn(instance.emit, ctx); } @@ -111,46 +239,22 @@ function initMocks(instance, mpInstance, mocks) { ctx[mock] = mpInstance[mock]; } }); -} - -const encode = encodeURIComponent; -function stringifyQuery(obj, encodeStr = encode) { - const res = obj - ? Object.keys(obj) - .map((key) => { - let val = obj[key]; - if (typeof val === undefined || val === null) { - val = ''; - } - else if (isPlainObject(val)) { - val = JSON.stringify(val); - } - return encodeStr(key) + '=' + encodeStr(val); - }) - .filter((x) => x.length > 0) - .join('&') - : null; - return res ? `?${res}` : ''; } -// lifecycle -// App and Page -const ON_SHOW = 'onShow'; -const ON_HIDE = 'onHide'; -//App -const ON_LAUNCH = 'onLaunch'; -const ON_ERROR = 'onError'; -const ON_THEME_CHANGE = 'onThemeChange'; -const ON_PAGE_NOT_FOUND = 'onPageNotFound'; -const ON_UNHANDLE_REJECTION = 'onUnhandledRejection'; -//Page -const ON_LOAD = 'onLoad'; -const ON_READY = 'onReady'; -const ON_UNLOAD = 'onUnload'; -const ON_RESIZE = 'onResize'; -const ON_TAB_ITEM_TAP = 'onTabItemTap'; -const ON_REACH_BOTTOM = 'onReachBottom'; -const ON_PULL_DOWN_REFRESH = 'onPullDownRefresh'; -const ON_ADD_TO_FAVORITES = 'onAddToFavorites'; +function hasHook(name) { + const hooks = this.$[name]; + if (hooks && hooks.length) { + return true; + } + return false; +} +function callHook(name, args) { + if (name === 'onLoad' && args && args.__id__) { + this.__eventChannel__ = getEventChannel(args.__id__); + delete args.__id__; + } + const hooks = this.$[name]; + return hooks && invokeArrayFns(hooks, args); +} const PAGE_HOOKS = [ ON_LOAD, @@ -307,7 +411,7 @@ function initRefs(instance, mpInstance) { }); } function findVmByVueId(instance, vuePid) { - // TODO vue3 中 没有 $children + // 标准 vue3 中 没有 $children,定制了内核 const $children = instance.$children; // 优先查找直属(反向查找:https://github.com/dcloudio/uni-app/issues/1200) for (let i = $children.length - 1; i >= 0; i--) { @@ -1037,14 +1141,14 @@ function parse(componentOptions, { handleLink }) { } var parseComponentOptions = /*#__PURE__*/Object.freeze({ - __proto__: null, - mocks: mocks, - isPage: isPage, - instances: instances, - initRelation: initRelation, - handleLink: handleLink, - parse: parse, - initLifetimes: initLifetimes$1 + __proto__: null, + mocks: mocks, + isPage: isPage, + instances: instances, + initRelation: initRelation, + handleLink: handleLink, + parse: parse, + initLifetimes: initLifetimes$1 }); function initLifetimes(lifetimesOptions) { @@ -1074,18 +1178,19 @@ function initLifetimes(lifetimesOptions) { } var parsePageOptions = /*#__PURE__*/Object.freeze({ - __proto__: null, - mocks: mocks, - isPage: isPage, - initRelation: initRelation, - handleLink: handleLink, - parse: parse, - initLifetimes: initLifetimes + __proto__: null, + mocks: mocks, + isPage: isPage, + initRelation: initRelation, + handleLink: handleLink, + parse: parse, + initLifetimes: initLifetimes }); const createApp = initCreateApp(); const createPage = initCreatePage(parsePageOptions); const createComponent = initCreateComponent(parseComponentOptions); +tt.EventChannel = EventChannel; tt.createApp = createApp; tt.createPage = createPage; tt.createComponent = createComponent; diff --git a/packages/uni-mp-toutiao/src/api/protocols.ts b/packages/uni-mp-toutiao/src/api/protocols.ts index 9a424e41216ddc24079060052a2c33bd0f410e7a..550892810e5f79a3679c34e248b73c5ad6bb2de0 100644 --- a/packages/uni-mp-toutiao/src/api/protocols.ts +++ b/packages/uni-mp-toutiao/src/api/protocols.ts @@ -1,4 +1,4 @@ -export { redirectTo, previewImage } from '@dcloudio/uni-mp-core' +export { redirectTo, navigateTo, previewImage } from '@dcloudio/uni-mp-core' export const chooseImage = { args: { sizeType: false, diff --git a/packages/uni-mp-toutiao/src/runtime/index.ts b/packages/uni-mp-toutiao/src/runtime/index.ts index 7954965b7bb4fcb463da502348dae657a8072731..e0b1a3aeae8ec19f16c84aea6b0c19eaa86b7ca0 100644 --- a/packages/uni-mp-toutiao/src/runtime/index.ts +++ b/packages/uni-mp-toutiao/src/runtime/index.ts @@ -1,3 +1,4 @@ +import { EventChannel } from '@dcloudio/uni-shared' import { initCreateApp, initCreatePage, @@ -12,6 +13,7 @@ import * as parseComponentOptions from './parseComponentOptions' export const createApp = initCreateApp() export const createPage = initCreatePage(parsePageOptions) export const createComponent = initCreateComponent(parseComponentOptions) +;(tt as any).EventChannel = EventChannel ;(tt as any).createApp = createApp ;(tt as any).createPage = createPage ;(tt as any).createComponent = createComponent diff --git a/packages/uni-mp-weixin/dist/uni.api.esm.js b/packages/uni-mp-weixin/dist/uni.api.esm.js index e996999cefc8ecd14b945d1fc9eb11469a7e3487..bc7c0504708425ba983274536dfd178138548dbd 100644 --- a/packages/uni-mp-weixin/dist/uni.api.esm.js +++ b/packages/uni-mp-weixin/dist/uni.api.esm.js @@ -613,6 +613,26 @@ function initGetProvider(providers) { }; } +function addSafeAreaInsets(fromRes, toRes) { + if (fromRes.safeArea) { + const safeArea = fromRes.safeArea; + toRes.safeAreaInsets = { + top: safeArea.top, + left: safeArea.left, + right: fromRes.windowWidth - safeArea.right, + bottom: fromRes.windowHeight - safeArea.bottom, + }; + } +} + +const getSystemInfo = { + returnValue: addSafeAreaInsets, +}; + +const getSystemInfoSync = getSystemInfo; + +const redirectTo = {}; + const previewImage = { args(fromArgs, toArgs) { let currentIndex = parseInt(fromArgs.current); @@ -645,23 +665,7 @@ const previewImage = { loop: false, }; }, -}; -function addSafeAreaInsets(fromRes, toRes) { - if (fromRes.safeArea) { - const safeArea = fromRes.safeArea; - toRes.safeAreaInsets = { - top: safeArea.top, - left: safeArea.left, - right: fromRes.windowWidth - safeArea.right, - bottom: fromRes.windowHeight - safeArea.bottom, - }; - } -} -const getSystemInfo = { - returnValue: addSafeAreaInsets, -}; -const getSystemInfoSync = getSystemInfo; -const redirectTo = {}; +}; const getProvider = initGetProvider({ oauth: ['weixin'], diff --git a/packages/uni-mp-weixin/dist/uni.mp.esm.js b/packages/uni-mp-weixin/dist/uni.mp.esm.js index 5eb9c939a0b8bef4318061fec8f06b4f873dce45..bd897eb414b3fd467f10d91f2e157079ccbb2530 100644 --- a/packages/uni-mp-weixin/dist/uni.mp.esm.js +++ b/packages/uni-mp-weixin/dist/uni.mp.esm.js @@ -1,4 +1,61 @@ -import { isArray, hasOwn, toNumber, isPlainObject, isObject, isFunction, extend, NOOP, camelize } from '@vue/shared'; +import { isPlainObject, isArray, hasOwn, toNumber, isObject, isFunction, extend, NOOP, camelize } from '@vue/shared'; + +const encode = encodeURIComponent; +function stringifyQuery(obj, encodeStr = encode) { + const res = obj + ? Object.keys(obj) + .map((key) => { + let val = obj[key]; + if (typeof val === undefined || val === null) { + val = ''; + } + else if (isPlainObject(val)) { + val = JSON.stringify(val); + } + return encodeStr(key) + '=' + encodeStr(val); + }) + .filter((x) => x.length > 0) + .join('&') + : null; + return res ? `?${res}` : ''; +} +const invokeArrayFns = (fns, arg) => { + let ret; + for (let i = 0; i < fns.length; i++) { + ret = fns[i](arg); + } + return ret; +}; +// lifecycle +// App and Page +const ON_SHOW = 'onShow'; +const ON_HIDE = 'onHide'; +//App +const ON_LAUNCH = 'onLaunch'; +const ON_ERROR = 'onError'; +const ON_THEME_CHANGE = 'onThemeChange'; +const ON_PAGE_NOT_FOUND = 'onPageNotFound'; +const ON_UNHANDLE_REJECTION = 'onUnhandledRejection'; +//Page +const ON_LOAD = 'onLoad'; +const ON_READY = 'onReady'; +const ON_UNLOAD = 'onUnload'; +const ON_RESIZE = 'onResize'; +const ON_TAB_ITEM_TAP = 'onTabItemTap'; +const ON_REACH_BOTTOM = 'onReachBottom'; +const ON_PULL_DOWN_REFRESH = 'onPullDownRefresh'; +const ON_ADD_TO_FAVORITES = 'onAddToFavorites'; + +const eventChannels = {}; +const eventChannelStack = []; +function getEventChannel(id) { + if (id) { + const eventChannel = eventChannels[id]; + delete eventChannels[id]; + return eventChannel; + } + return eventChannelStack.shift(); +} function setModel(target, key, value, modifiers) { if (isArray(modifiers)) { @@ -82,6 +139,14 @@ function initBaseInstance(instance, options) { }); } } + ctx.getOpenerEventChannel = function () { + // 微信小程序使用自身getOpenerEventChannel + { + return options.mpInstance.getOpenerEventChannel(); + } + }; + ctx.$hasHook = hasHook; + ctx.$callHook = callHook; // $emit instance.emit = createEmitFn(instance.emit, ctx); } @@ -111,46 +176,22 @@ function initMocks(instance, mpInstance, mocks) { ctx[mock] = mpInstance[mock]; } }); -} - -const encode = encodeURIComponent; -function stringifyQuery(obj, encodeStr = encode) { - const res = obj - ? Object.keys(obj) - .map((key) => { - let val = obj[key]; - if (typeof val === undefined || val === null) { - val = ''; - } - else if (isPlainObject(val)) { - val = JSON.stringify(val); - } - return encodeStr(key) + '=' + encodeStr(val); - }) - .filter((x) => x.length > 0) - .join('&') - : null; - return res ? `?${res}` : ''; } -// lifecycle -// App and Page -const ON_SHOW = 'onShow'; -const ON_HIDE = 'onHide'; -//App -const ON_LAUNCH = 'onLaunch'; -const ON_ERROR = 'onError'; -const ON_THEME_CHANGE = 'onThemeChange'; -const ON_PAGE_NOT_FOUND = 'onPageNotFound'; -const ON_UNHANDLE_REJECTION = 'onUnhandledRejection'; -//Page -const ON_LOAD = 'onLoad'; -const ON_READY = 'onReady'; -const ON_UNLOAD = 'onUnload'; -const ON_RESIZE = 'onResize'; -const ON_TAB_ITEM_TAP = 'onTabItemTap'; -const ON_REACH_BOTTOM = 'onReachBottom'; -const ON_PULL_DOWN_REFRESH = 'onPullDownRefresh'; -const ON_ADD_TO_FAVORITES = 'onAddToFavorites'; +function hasHook(name) { + const hooks = this.$[name]; + if (hooks && hooks.length) { + return true; + } + return false; +} +function callHook(name, args) { + if (name === 'onLoad' && args && args.__id__) { + this.__eventChannel__ = getEventChannel(args.__id__); + delete args.__id__; + } + const hooks = this.$[name]; + return hooks && invokeArrayFns(hooks, args); +} const PAGE_HOOKS = [ ON_LOAD, @@ -304,7 +345,7 @@ function initRefs(instance, mpInstance) { }); } function findVmByVueId(instance, vuePid) { - // TODO vue3 中 没有 $children + // 标准 vue3 中 没有 $children,定制了内核 const $children = instance.$children; // 优先查找直属(反向查找:https://github.com/dcloudio/uni-app/issues/1200) for (let i = $children.length - 1; i >= 0; i--) { @@ -916,12 +957,12 @@ function handleLink(event) { } var parseOptions = /*#__PURE__*/Object.freeze({ - __proto__: null, - mocks: mocks, - isPage: isPage, - initRelation: initRelation, - handleLink: handleLink, - initLifetimes: initLifetimes + __proto__: null, + mocks: mocks, + isPage: isPage, + initRelation: initRelation, + handleLink: handleLink, + initLifetimes: initLifetimes }); const createApp = initCreateApp(); diff --git a/packages/uni-quickapp-webview/dist/uni.api.esm.js b/packages/uni-quickapp-webview/dist/uni.api.esm.js index d929c5c9cfaaade6d9f7b279cd125525ee8a118f..9d5741cfbebcce9547e4f6e8b80b52179a7be0ba 100644 --- a/packages/uni-quickapp-webview/dist/uni.api.esm.js +++ b/packages/uni-quickapp-webview/dist/uni.api.esm.js @@ -1,5 +1,41 @@ import { isArray, hasOwn, isString, isPlainObject, isObject, capitalize, toRawType, makeMap, isPromise, isFunction, extend } from '@vue/shared'; +const eventChannels = {}; +const eventChannelStack = []; +let id = 0; +function initEventChannel(events, cache = true) { + id++; + const eventChannel = new qa.EventChannel(id, events); + if (cache) { + eventChannels[id] = eventChannel; + eventChannelStack.push(eventChannel); + } + return eventChannel; +} +function getEventChannel(id) { + if (id) { + const eventChannel = eventChannels[id]; + delete eventChannels[id]; + return eventChannel; + } + return eventChannelStack.shift(); +} +const navigateTo = { + args(fromArgs) { + const id = initEventChannel(fromArgs.events).id; + if (fromArgs.url) { + fromArgs.url = + fromArgs.url + + (fromArgs.url.indexOf('?') === -1 ? '?' : '&') + + '__id__=' + + id; + } + }, + returnValue(fromRes) { + fromRes.eventChannel = getEventChannel(); + }, +}; + function getBaseSystemInfo() { return qa.getSystemInfoSync() } @@ -613,6 +649,26 @@ function initGetProvider(providers) { }; } +function addSafeAreaInsets(fromRes, toRes) { + if (fromRes.safeArea) { + const safeArea = fromRes.safeArea; + toRes.safeAreaInsets = { + top: safeArea.top, + left: safeArea.left, + right: fromRes.windowWidth - safeArea.right, + bottom: fromRes.windowHeight - safeArea.bottom, + }; + } +} + +const getSystemInfo = { + returnValue: addSafeAreaInsets, +}; + +const getSystemInfoSync = getSystemInfo; + +const redirectTo = {}; + const previewImage = { args(fromArgs, toArgs) { let currentIndex = parseInt(fromArgs.current); @@ -645,23 +701,7 @@ const previewImage = { loop: false, }; }, -}; -function addSafeAreaInsets(fromRes, toRes) { - if (fromRes.safeArea) { - const safeArea = fromRes.safeArea; - toRes.safeAreaInsets = { - top: safeArea.top, - left: safeArea.left, - right: fromRes.windowWidth - safeArea.right, - bottom: fromRes.windowHeight - safeArea.bottom, - }; - } -} -const getSystemInfo = { - returnValue: addSafeAreaInsets, -}; -const getSystemInfoSync = getSystemInfo; -const redirectTo = {}; +}; const providers = { oauth: [], @@ -685,6 +725,7 @@ var shims = /*#__PURE__*/Object.freeze({ var protocols = /*#__PURE__*/Object.freeze({ __proto__: null, redirectTo: redirectTo, + navigateTo: navigateTo, previewImage: previewImage, getSystemInfo: getSystemInfo, getSystemInfoSync: getSystemInfoSync diff --git a/packages/uni-quickapp-webview/dist/uni.mp.esm.js b/packages/uni-quickapp-webview/dist/uni.mp.esm.js index 20a79eea1308e63da1b51fdf980f1a5ec36cd0ec..d473513401e8241966f823984a24548f838f3dab 100644 --- a/packages/uni-quickapp-webview/dist/uni.mp.esm.js +++ b/packages/uni-quickapp-webview/dist/uni.mp.esm.js @@ -1,4 +1,124 @@ -import { isArray, hasOwn, toNumber, isPlainObject, isObject, isFunction, extend, NOOP, camelize } from '@vue/shared'; +import { isPlainObject, isArray, hasOwn, toNumber, isObject, isFunction, extend, NOOP, camelize } from '@vue/shared'; + +const encode = encodeURIComponent; +function stringifyQuery(obj, encodeStr = encode) { + const res = obj + ? Object.keys(obj) + .map((key) => { + let val = obj[key]; + if (typeof val === undefined || val === null) { + val = ''; + } + else if (isPlainObject(val)) { + val = JSON.stringify(val); + } + return encodeStr(key) + '=' + encodeStr(val); + }) + .filter((x) => x.length > 0) + .join('&') + : null; + return res ? `?${res}` : ''; +} +const invokeArrayFns = (fns, arg) => { + let ret; + for (let i = 0; i < fns.length; i++) { + ret = fns[i](arg); + } + return ret; +}; +// lifecycle +// App and Page +const ON_SHOW = 'onShow'; +const ON_HIDE = 'onHide'; +//App +const ON_LAUNCH = 'onLaunch'; +const ON_ERROR = 'onError'; +const ON_THEME_CHANGE = 'onThemeChange'; +const ON_PAGE_NOT_FOUND = 'onPageNotFound'; +const ON_UNHANDLE_REJECTION = 'onUnhandledRejection'; +//Page +const ON_LOAD = 'onLoad'; +const ON_READY = 'onReady'; +const ON_UNLOAD = 'onUnload'; +const ON_RESIZE = 'onResize'; +const ON_TAB_ITEM_TAP = 'onTabItemTap'; +const ON_REACH_BOTTOM = 'onReachBottom'; +const ON_PULL_DOWN_REFRESH = 'onPullDownRefresh'; +const ON_ADD_TO_FAVORITES = 'onAddToFavorites'; + +class EventChannel { + constructor(id, events) { + this.id = id; + this.listener = {}; + this.emitCache = {}; + if (events) { + Object.keys(events).forEach((name) => { + this.on(name, events[name]); + }); + } + } + emit(eventName, ...args) { + const fns = this.listener[eventName]; + if (!fns) { + return (this.emitCache[eventName] || (this.emitCache[eventName] = [])).push(args); + } + fns.forEach((opt) => { + opt.fn.apply(opt.fn, args); + }); + this.listener[eventName] = fns.filter((opt) => opt.type !== 'once'); + } + on(eventName, fn) { + this._addListener(eventName, 'on', fn); + this._clearCache(eventName); + } + once(eventName, fn) { + this._addListener(eventName, 'once', fn); + this._clearCache(eventName); + } + off(eventName, fn) { + const fns = this.listener[eventName]; + if (!fns) { + return; + } + if (fn) { + for (let i = 0; i < fns.length;) { + if (fns[i].fn === fn) { + fns.splice(i, 1); + i--; + } + i++; + } + } + else { + delete this.listener[eventName]; + } + } + _clearCache(eventName) { + const cacheArgs = this.emitCache[eventName]; + if (cacheArgs) { + for (; cacheArgs.length > 0;) { + this.emit.apply(this, [eventName, ...cacheArgs.shift()]); + } + } + } + _addListener(eventName, type, fn) { + (this.listener[eventName] || (this.listener[eventName] = [])).push({ + fn, + type, + }); + } +} + +const eventChannels = {}; +const eventChannelStack = []; +function getEventChannel(id) { + if (id) { + const eventChannel = eventChannels[id]; + delete eventChannels[id]; + return eventChannel; + } + return eventChannelStack.shift(); +} function setModel(target, key, value, modifiers) { if (isArray(modifiers)) { @@ -82,6 +202,14 @@ function initBaseInstance(instance, options) { }); } } + ctx.getOpenerEventChannel = function () { + if (!this.__eventChannel__) { + this.__eventChannel__ = new EventChannel(); + } + return this.__eventChannel__; + }; + ctx.$hasHook = hasHook; + ctx.$callHook = callHook; // $emit instance.emit = createEmitFn(instance.emit, ctx); } @@ -111,46 +239,22 @@ function initMocks(instance, mpInstance, mocks) { ctx[mock] = mpInstance[mock]; } }); -} - -const encode = encodeURIComponent; -function stringifyQuery(obj, encodeStr = encode) { - const res = obj - ? Object.keys(obj) - .map((key) => { - let val = obj[key]; - if (typeof val === undefined || val === null) { - val = ''; - } - else if (isPlainObject(val)) { - val = JSON.stringify(val); - } - return encodeStr(key) + '=' + encodeStr(val); - }) - .filter((x) => x.length > 0) - .join('&') - : null; - return res ? `?${res}` : ''; } -// lifecycle -// App and Page -const ON_SHOW = 'onShow'; -const ON_HIDE = 'onHide'; -//App -const ON_LAUNCH = 'onLaunch'; -const ON_ERROR = 'onError'; -const ON_THEME_CHANGE = 'onThemeChange'; -const ON_PAGE_NOT_FOUND = 'onPageNotFound'; -const ON_UNHANDLE_REJECTION = 'onUnhandledRejection'; -//Page -const ON_LOAD = 'onLoad'; -const ON_READY = 'onReady'; -const ON_UNLOAD = 'onUnload'; -const ON_RESIZE = 'onResize'; -const ON_TAB_ITEM_TAP = 'onTabItemTap'; -const ON_REACH_BOTTOM = 'onReachBottom'; -const ON_PULL_DOWN_REFRESH = 'onPullDownRefresh'; -const ON_ADD_TO_FAVORITES = 'onAddToFavorites'; +function hasHook(name) { + const hooks = this.$[name]; + if (hooks && hooks.length) { + return true; + } + return false; +} +function callHook(name, args) { + if (name === 'onLoad' && args && args.__id__) { + this.__eventChannel__ = getEventChannel(args.__id__); + delete args.__id__; + } + const hooks = this.$[name]; + return hooks && invokeArrayFns(hooks, args); +} const PAGE_HOOKS = [ ON_LOAD, @@ -1050,28 +1154,29 @@ function handleLink({ detail: { nodeId, webviewId }, }) { } var parseComponentOptions = /*#__PURE__*/Object.freeze({ - __proto__: null, - initRelation: initRelation, - handleLink: handleLink, - mocks: mocks, - isPage: isPage, - parse: parse, - initLifetimes: initLifetimes$1 + __proto__: null, + initRelation: initRelation, + handleLink: handleLink, + mocks: mocks, + isPage: isPage, + parse: parse, + initLifetimes: initLifetimes$1 }); var parsePageOptions = /*#__PURE__*/Object.freeze({ - __proto__: null, - mocks: mocks, - isPage: isPage, - initRelation: initRelation, - handleLink: handleLink, - parse: parse, - initLifetimes: initLifetimes + __proto__: null, + mocks: mocks, + isPage: isPage, + initRelation: initRelation, + handleLink: handleLink, + parse: parse, + initLifetimes: initLifetimes }); const createApp = initCreateApp(); const createPage = initCreatePage(parsePageOptions); const createComponent = initCreateComponent(parseComponentOptions); +qa.EventChannel = EventChannel; qa.createApp = createApp; qa.createPage = createPage; qa.createComponent = createComponent; diff --git a/packages/uni-quickapp-webview/src/api/protocols.ts b/packages/uni-quickapp-webview/src/api/protocols.ts index fdbeb102291695af6b390a6cb97999e009643c41..0a42f0fbdbb535be49242a869d0448bb2361d88e 100644 --- a/packages/uni-quickapp-webview/src/api/protocols.ts +++ b/packages/uni-quickapp-webview/src/api/protocols.ts @@ -1,5 +1,6 @@ export { redirectTo, + navigateTo, previewImage, getSystemInfo, getSystemInfoSync, diff --git a/packages/uni-quickapp-webview/src/runtime/index.ts b/packages/uni-quickapp-webview/src/runtime/index.ts index ff2c67606a093894b23ff2606cbe0ab2af7ff909..62dd7874ca360bee497ed304d57f426c79e9464c 100644 --- a/packages/uni-quickapp-webview/src/runtime/index.ts +++ b/packages/uni-quickapp-webview/src/runtime/index.ts @@ -1,3 +1,4 @@ +import { EventChannel } from '@dcloudio/uni-shared' import { initCreateApp, initCreatePage, @@ -12,6 +13,7 @@ import * as parseComponentOptions from './parseComponentOptions' export const createApp = initCreateApp() export const createPage = initCreatePage(parsePageOptions) export const createComponent = initCreateComponent(parseComponentOptions) +;(qa as any).EventChannel = EventChannel ;(qa as any).createApp = createApp ;(qa as any).createPage = createPage ;(qa as any).createComponent = createComponent diff --git a/packages/uni-shared/src/EventChannel.ts b/packages/uni-shared/src/EventChannel.ts index ed5f6a15ef3eb36b8099514108d26e471d73432d..e4ea975106aff34e066ba5f8742b743f8dc11cac 100644 --- a/packages/uni-shared/src/EventChannel.ts +++ b/packages/uni-shared/src/EventChannel.ts @@ -6,10 +6,10 @@ interface EventChannelListener { } export class EventChannel { - id: number + id?: number private listener: Record private emitCache: Record - constructor(id: number, events?: NavigateToOptionEvents) { + constructor(id?: number, events?: NavigateToOptionEvents) { this.id = id this.listener = {} this.emitCache = {} diff --git a/packages/uni-vue/src/componentInstance.ts b/packages/uni-vue/src/componentInstance.ts index 671e05a007ea0aab0102744d7866a0f403444e21..cc4c5d9cb1e375cef47ab26ab1425c37f73eae98 100644 --- a/packages/uni-vue/src/componentInstance.ts +++ b/packages/uni-vue/src/componentInstance.ts @@ -1,23 +1,3 @@ -import { ComponentPublicInstance } from 'vue' -import { invokeArrayFns } from '@dcloudio/uni-shared' - export function set(target: any, key: string | number, val: unknown) { return (target[key] = val) } - -export function hasHook(this: ComponentPublicInstance, name: string) { - const hooks = (this.$ as any)[name] - if (hooks && hooks.length) { - return true - } - return false -} - -export function callHook( - this: ComponentPublicInstance, - name: string, - args?: unknown -) { - const hooks = (this.$ as any)[name] - return hooks && invokeArrayFns(hooks, args) -} diff --git a/packages/uni-vue/src/index.ts b/packages/uni-vue/src/index.ts index 2a9eb8cb0b670a3099f278f41d32b5da4c399e14..2773a8fbac6ffa1591e482632a6d78388e59a181 100644 --- a/packages/uni-vue/src/index.ts +++ b/packages/uni-vue/src/index.ts @@ -3,7 +3,7 @@ import { App } from 'vue' import { isFunction } from '@vue/shared' import { applyOptions } from './componentOptions' -import { set, hasHook, callHook } from './componentInstance' +import { set } from './componentInstance' import { errorHandler } from './appConfig' import { uniIdMixin } from './uni-id-mixin' @@ -14,11 +14,6 @@ export function initApp(app: App) { } const globalProperties = appConfig.globalProperties uniIdMixin(globalProperties) - if (__PLATFORM__ !== 'h5' && __PLATFORM__ !== 'app') { - // 小程序,待重构,不再挂靠全局 - globalProperties.$hasHook = hasHook - globalProperties.$callHook = callHook - } if (__VUE_OPTIONS_API__) { globalProperties.$set = set globalProperties.$applyOptions = applyOptions