From 155bfc5aa6fd98267edf3ac2d51f52b06f9d5822 Mon Sep 17 00:00:00 2001 From: fxy060608 Date: Wed, 30 Oct 2019 16:16:28 +0800 Subject: [PATCH] feat(v3): add $nextTick --- packages/uni-app-plus/dist/index.v3.js | 258 ++++++++++++++++-- .../uni-app-plus/dist/service.runtime.esm.js | 4 +- .../wrapper/create-vue-component/index.js | 13 +- .../parser/behaviors-parser.js | 24 +- .../parser/definition-filter-parser.js | 36 ++- .../parser/external-classes-parser.js | 3 +- .../create-vue-component/parser/index.js | 26 +- .../parser/lifecycle-parser.js | 19 +- .../parser/lifetimes-parser.js | 7 +- .../parser/options-parser.js | 3 +- .../parser/relations-parser.js | 3 +- .../service/framework/plugins/index.js | 16 ++ 12 files changed, 361 insertions(+), 51 deletions(-) diff --git a/packages/uni-app-plus/dist/index.v3.js b/packages/uni-app-plus/dist/index.v3.js index 298c08b79..c0fb3a609 100644 --- a/packages/uni-app-plus/dist/index.v3.js +++ b/packages/uni-app-plus/dist/index.v3.js @@ -3004,6 +3004,210 @@ var serviceContext = (function () { return data } + function operateMapPlayer (mapId, pageVm, type, data) { + const pageId = pageVm.$page.id; + UniServiceJSBridge.publishHandler(pageId + '-map-' + mapId, { + mapId, + type, + data + }, pageId); + } + + const SUCCESS = 'success'; + const FAIL = 'fail'; + const COMPLETE = 'complete'; + const CALLBACKS = [SUCCESS, FAIL, COMPLETE]; + + /** + * 调用无参数,或仅一个参数且为 callback 的 API + * @param {Object} vm + * @param {Object} method + * @param {Object} args + * @param {Object} extras + */ + function invokeVmMethodWithoutArgs (vm, method, args, extras) { + if (!vm) { + return + } + if (typeof args === 'undefined') { + return vm[method]() + } + const [, callbacks] = normalizeArgs(args, extras); + if (!Object.keys(callbacks).length) { + return vm[method]() + } + return vm[method](normalizeCallback(method, callbacks)) + } + /** + * 调用两个参数(第一个入参为普通参数,第二个入参为 callback) API + * @param {Object} vm + * @param {Object} method + * @param {Object} args + * @param {Object} extras + */ + function invokeVmMethod (vm, method, args, extras) { + if (!vm) { + return + } + const [pureArgs, callbacks] = normalizeArgs(args, extras); + if (!Object.keys(callbacks).length) { + return vm[method](pureArgs) + } + return vm[method](pureArgs, normalizeCallback(method, callbacks)) + } + + function findElmById (id, vm) { + const elm = findRefByElm(id, vm.$el); + if (!elm) { + return console.error('Can not find `' + id + '`') + } + return elm + } + + function findRefByElm (id, elm) { + if (!id || !elm) { + return + } + if (elm.attr.id === id) { + return elm + } + const children = elm.children; + if (!children) { + return + } + for (let i = 0, len = children.length; i < len; i++) { + const elm = findRefByElm(id, children[i]); + if (elm) { + return elm + } + } + } + + function normalizeArgs (args = {}, extras) { + const callbacks = Object.create(null); + + const iterator = function iterator (name) { + const callback = args[name]; + if (isFn(callback)) { + callbacks[name] = callback; + delete args[name]; + } + }; + + CALLBACKS.forEach(iterator); + + extras && extras.forEach(iterator); + + return [args, callbacks] + } + + function normalizeCallback (method, callbacks) { + return function weexCallback (ret) { + const type = ret.type; + delete ret.type; + const callback = callbacks[type]; + + if (type === SUCCESS) { + ret.errMsg = `${method}:ok`; + } else if (type === FAIL) { + ret.errMsg = method + ':fail' + (ret.msg ? (' ' + ret.msg) : ''); + } + + delete ret.code; + delete ret.msg; + + isFn(callback) && callback(ret); + + if (type === SUCCESS || type === FAIL) { + const complete = callbacks['complete']; + isFn(complete) && complete(ret); + } + } + } + + const METHODS = { + getCenterLocation (ctx, cbs) { + return invokeVmMethodWithoutArgs(ctx, 'getCenterLocation', cbs) + }, + moveToLocation (ctx) { + return invokeVmMethodWithoutArgs(ctx, 'moveToLocation') + }, + translateMarker (ctx, args) { + return invokeVmMethod(ctx, 'translateMarker', args, ['animationEnd']) + }, + includePoints (ctx, args) { + return invokeVmMethod(ctx, 'includePoints', args) + }, + getRegion (ctx, cbs) { + return invokeVmMethodWithoutArgs(ctx, 'getRegion', cbs) + }, + getScale (ctx, cbs) { + return invokeVmMethodWithoutArgs(ctx, 'getScale', cbs) + } + }; + + function operateMapPlayer$1 (mapId, pageVm, type, data) { + return METHODS[type](findElmById(mapId, pageVm), data) + } + + function operateMapPlayer$2 (mapId, pageVm, type, data) { + pageVm.$page.meta.isNVue + ? operateMapPlayer$1(mapId, pageVm, type, data) + : operateMapPlayer(mapId, pageVm, type, data); + } + + function operateVideoPlayer (videoId, pageVm, type, data) { + const pageId = pageVm.$page.id; + UniServiceJSBridge.publishHandler(pageId + '-video-' + videoId, { + videoId, + type, + data + }, pageId); + } + + const METHODS$1 = { + play (ctx) { + return invokeVmMethodWithoutArgs(ctx, 'play') + }, + pause (ctx) { + return invokeVmMethodWithoutArgs(ctx, 'pause') + }, + seek (ctx, args) { + return invokeVmMethod(ctx, 'seek', args) + }, + stop (ctx) { + return invokeVmMethodWithoutArgs(ctx, 'stop') + }, + sendDanmu (ctx, args) { + return invokeVmMethod(ctx, 'sendDanmu', args) + }, + playbackRate (ctx, args) { + return invokeVmMethod(ctx, 'playbackRate', args) + }, + requestFullScreen (ctx, args) { + return invokeVmMethod(ctx, 'requestFullScreen', args) + }, + exitFullScreen (ctx) { + return invokeVmMethodWithoutArgs(ctx, 'exitFullScreen') + }, + showStatusBar (ctx) { + return invokeVmMethodWithoutArgs(ctx, 'showStatusBar') + }, + hideStatusBar (ctx) { + return invokeVmMethodWithoutArgs(ctx, 'hideStatusBar') + } + }; + + function operateVideoPlayer$1 (videoId, pageVm, type, data) { + return METHODS$1[type](findElmById(videoId, pageVm), data) + } + + function operateVideoPlayer$2 (videoId, pageVm, type, data) { + pageVm.$page.meta.isNVue + ? operateVideoPlayer$1(videoId, pageVm, type, data) + : operateVideoPlayer(videoId, pageVm, type, data); + } + const DEVICE_FREQUENCY = 200; const NETWORK_TYPES = ['unknown', 'none', 'ethernet', 'wifi', '2g', '3g', '4g']; @@ -7267,12 +7471,14 @@ var serviceContext = (function () { var api = /*#__PURE__*/Object.freeze({ startPullDownRefresh: startPullDownRefresh, stopPullDownRefresh: stopPullDownRefresh, - previewImage: previewImage$1, + getImageInfo: getImageInfo$1, createAudioInstance: createAudioInstance, destroyAudioInstance: destroyAudioInstance, setAudioState: setAudioState, getAudioState: getAudioState, operateAudio: operateAudio, + operateMapPlayer: operateMapPlayer$2, + operateVideoPlayer: operateVideoPlayer$2, enableAccelerometer: enableAccelerometer, addPhoneContact: addPhoneContact, openBluetoothAdapter: openBluetoothAdapter, @@ -7327,12 +7533,12 @@ var serviceContext = (function () { chooseImage: chooseImage$1, chooseVideo: chooseVideo$1, compressImage: compressImage, - getImageInfo: getImageInfo$1, getMusicPlayerState: getMusicPlayerState, operateMusicPlayer: operateMusicPlayer, setBackgroundAudioState: setBackgroundAudioState, operateBackgroundAudio: operateBackgroundAudio, getBackgroundAudioState: getBackgroundAudioState, + previewImage: previewImage$1, operateRecorder: operateRecorder, saveImageToPhotosAlbum: saveImageToPhotosAlbum, saveVideoToPhotosAlbum: saveVideoToPhotosAlbum, @@ -7747,7 +7953,7 @@ var serviceContext = (function () { getBackgroundAudioManager: getBackgroundAudioManager }); - function operateMapPlayer (mapId, pageVm, type, data) { + function operateMapPlayer$3 (mapId, pageVm, type, data) { invokeMethod('operateMapPlayer', mapId, pageVm, type, data); } @@ -7758,27 +7964,27 @@ var serviceContext = (function () { } getCenterLocation (args) { - operateMapPlayer(this.id, this.pageVm, 'getCenterLocation', args); + operateMapPlayer$3(this.id, this.pageVm, 'getCenterLocation', args); } moveToLocation () { - operateMapPlayer(this.id, this.pageVm, 'moveToLocation'); + operateMapPlayer$3(this.id, this.pageVm, 'moveToLocation'); } translateMarker (args) { - operateMapPlayer(this.id, this.pageVm, 'translateMarker', args); + operateMapPlayer$3(this.id, this.pageVm, 'translateMarker', args); } includePoints (args) { - operateMapPlayer(this.id, this.pageVm, 'includePoints', args); + operateMapPlayer$3(this.id, this.pageVm, 'includePoints', args); } getRegion (args) { - operateMapPlayer(this.id, this.pageVm, 'getRegion', args); + operateMapPlayer$3(this.id, this.pageVm, 'getRegion', args); } getScale (args) { - operateMapPlayer(this.id, this.pageVm, 'getScale', args); + operateMapPlayer$3(this.id, this.pageVm, 'getScale', args); } } @@ -7795,7 +8001,7 @@ var serviceContext = (function () { const RATES = [0.5, 0.8, 1.0, 1.25, 1.5]; - function operateVideoPlayer (videoId, pageVm, type, data) { + function operateVideoPlayer$3 (videoId, pageVm, type, data) { invokeMethod('operateVideoPlayer', videoId, pageVm, type, data); } @@ -7806,41 +8012,41 @@ var serviceContext = (function () { } play () { - operateVideoPlayer(this.id, this.pageVm, 'play'); + operateVideoPlayer$3(this.id, this.pageVm, 'play'); } pause () { - operateVideoPlayer(this.id, this.pageVm, 'pause'); + operateVideoPlayer$3(this.id, this.pageVm, 'pause'); } stop () { - operateVideoPlayer(this.id, this.pageVm, 'stop'); + operateVideoPlayer$3(this.id, this.pageVm, 'stop'); } seek (position) { - operateVideoPlayer(this.id, this.pageVm, 'seek', { + operateVideoPlayer$3(this.id, this.pageVm, 'seek', { position }); } sendDanmu (args) { - operateVideoPlayer(this.id, this.pageVm, 'sendDanmu', args); + operateVideoPlayer$3(this.id, this.pageVm, 'sendDanmu', args); } playbackRate (rate) { if (!~RATES.indexOf(rate)) { rate = 1.0; } - operateVideoPlayer(this.id, this.pageVm, 'playbackRate', { + operateVideoPlayer$3(this.id, this.pageVm, 'playbackRate', { rate }); } requestFullScreen () { - operateVideoPlayer(this.id, this.pageVm, 'requestFullScreen'); + operateVideoPlayer$3(this.id, this.pageVm, 'requestFullScreen'); } exitFullScreen () { - operateVideoPlayer(this.id, this.pageVm, 'exitFullScreen'); + operateVideoPlayer$3(this.id, this.pageVm, 'exitFullScreen'); } showStatusBar () { - operateVideoPlayer(this.id, this.pageVm, 'showStatusBar'); + operateVideoPlayer$3(this.id, this.pageVm, 'showStatusBar'); } hideStatusBar () { - operateVideoPlayer(this.id, this.pageVm, 'hideStatusBar'); + operateVideoPlayer$3(this.id, this.pageVm, 'hideStatusBar'); } } @@ -10012,6 +10218,18 @@ var serviceContext = (function () { } return oldMount.call(this, el, hydrating) }; + + Vue.prototype.$nextTick = function nextTick (cb) { + const renderWatcher = this._watcher; + if ( + renderWatcher && + this._$queue.find(watcher => renderWatcher === watcher) + ) { + vdSyncCallbacks.push(cb); + } else { + Vue.nextTick(cb); + } + }; } }; diff --git a/packages/uni-app-plus/dist/service.runtime.esm.js b/packages/uni-app-plus/dist/service.runtime.esm.js index 58d567f9c..b2c7602ae 100644 --- a/packages/uni-app-plus/dist/service.runtime.esm.js +++ b/packages/uni-app-plus/dist/service.runtime.esm.js @@ -4232,7 +4232,7 @@ function callHook (vm, hook) { var MAX_UPDATE_COUNT = 100; -var queue = []; +var queue = []; // fixed by xxxxxx var activatedChildren = []; var has = {}; var circular = {}; @@ -6789,6 +6789,8 @@ function callHook$2(hook, args) { var plugin = { install: function install(Vue) { + + Vue.prototype._$queue = queue; Vue.prototype._m = function renderStatic() { return this._e() diff --git a/src/core/runtime/wrapper/create-vue-component/index.js b/src/core/runtime/wrapper/create-vue-component/index.js index 91c96bc84..c47ecdfd8 100644 --- a/src/core/runtime/wrapper/create-vue-component/index.js +++ b/src/core/runtime/wrapper/create-vue-component/index.js @@ -1,14 +1,7 @@ import { - parseProperties + parseComponentOptions } from './parser' -export default function createVueComponent (mpComponentOptions) { - const vueComponentOptions = { - watch: {}, - mpObservers: [] - } - - parseProperties(mpComponentOptions.properties, vueComponentOptions) - - return vueComponentOptions +export default function createVueComponent (mpComponentOptions) { + return parseComponentOptions(mpComponentOptions) } diff --git a/src/core/runtime/wrapper/create-vue-component/parser/behaviors-parser.js b/src/core/runtime/wrapper/create-vue-component/parser/behaviors-parser.js index 8c428b172..bf367ccf2 100644 --- a/src/core/runtime/wrapper/create-vue-component/parser/behaviors-parser.js +++ b/src/core/runtime/wrapper/create-vue-component/parser/behaviors-parser.js @@ -1,5 +1,27 @@ +import { + parseComponentOptions +} from './index' + +const mixins = { + 'wx://form-field': { + + }, + 'wx://component-export': { + + } +} + +function parseBehavior (behavior) { + if (typeof behavior === 'string') { + return mixins[behavior] + } + return parseComponentOptions(behavior) +} + export function parseBehaviors (behaviors, vueComponentOptions) { if (!behaviors) { - + vueComponentOptions.mixins = behaviors.forEach(behavior => { + return parseBehavior(behavior) + }) } } diff --git a/src/core/runtime/wrapper/create-vue-component/parser/definition-filter-parser.js b/src/core/runtime/wrapper/create-vue-component/parser/definition-filter-parser.js index 4a1bf43bc..5a9cab03a 100644 --- a/src/core/runtime/wrapper/create-vue-component/parser/definition-filter-parser.js +++ b/src/core/runtime/wrapper/create-vue-component/parser/definition-filter-parser.js @@ -1,5 +1,37 @@ -export function parseDefinitionFilter (definitionFilter, vueComponentOptions) { - if (!definitionFilter) { +import { + isFn +} from 'uni-shared' +const mpBehaviors = { + 'wx://form-field': {}, + 'wx://component-export': {} +} + +function callDefinitionFilter (mpComponentOptions) { + const { + behaviors, + definitionFilter + } = mpComponentOptions + + const behaviorDefinitionFilters = [] + + if (Array.isArray(behaviors)) { + behaviors.forEach(behavior => { + behavior = typeof behavior === 'string' ? mpBehaviors[behavior] : behavior + if (behavior.definitionFilter) { + behaviorDefinitionFilters.push(behavior.definitionFilter) + behavior.definitionFilter.call(null, mpComponentOptions, []) + } + }) } + + if (isFn(definitionFilter)) { + return function (defFields) { + definitionFilter(defFields, behaviorDefinitionFilters) + } + } +} + +export function parseDefinitionFilter (mpComponentOptions, vueComponentOptions) { + callDefinitionFilter(mpComponentOptions) } diff --git a/src/core/runtime/wrapper/create-vue-component/parser/external-classes-parser.js b/src/core/runtime/wrapper/create-vue-component/parser/external-classes-parser.js index 89410206d..56b1c05aa 100644 --- a/src/core/runtime/wrapper/create-vue-component/parser/external-classes-parser.js +++ b/src/core/runtime/wrapper/create-vue-component/parser/external-classes-parser.js @@ -1,5 +1,6 @@ export function parseExternalClasses (externalClasses, vueComponentOptions) { if (!externalClasses) { - + return } + vueComponentOptions.mpExternalClasses = externalClasses } diff --git a/src/core/runtime/wrapper/create-vue-component/parser/index.js b/src/core/runtime/wrapper/create-vue-component/parser/index.js index 7804643ff..faeaad15a 100644 --- a/src/core/runtime/wrapper/create-vue-component/parser/index.js +++ b/src/core/runtime/wrapper/create-vue-component/parser/index.js @@ -1,12 +1,14 @@ -export * from './proerties-parser' -export * from './data-parser' -export * from './observers-parser' -export * from './behaviors-parser' -export * from './methods-parser' -export * from './lifecycle-parser' -export * from './relations-parser' -export * from './external-classes-parser' -export * from './options-parser' -export * from './lifetimes-parser' -export * from './page-lifetimes-parser' -export * from './definition-filter-parser' +import { + parseProperties +} from './parser' + +export function parseComponentOptions (mpComponentOptions) { + const vueComponentOptions = { + watch: {}, + mpObservers: [] + } + + parseProperties(mpComponentOptions.properties, vueComponentOptions) + + return vueComponentOptions +} diff --git a/src/core/runtime/wrapper/create-vue-component/parser/lifecycle-parser.js b/src/core/runtime/wrapper/create-vue-component/parser/lifecycle-parser.js index 8fd176260..1761407de 100644 --- a/src/core/runtime/wrapper/create-vue-component/parser/lifecycle-parser.js +++ b/src/core/runtime/wrapper/create-vue-component/parser/lifecycle-parser.js @@ -1,3 +1,20 @@ -export function parseLifecycle (mpComponentOptions, vueComponentOptions) { +import { + hasOwn +} from 'uni-shared' + +const LIFECYCLE = { + 'created': 'created', + 'attached': 'created', + 'ready': 'mounted', + 'moved': 'moved', + 'detached': 'destroyed' +} +const LIFECYCLE_KEYS = Object.keys(LIFECYCLE) +export function parseLifecycle (mpComponentOptions, vueComponentOptions) { + Object.keys(LIFECYCLE_KEYS).forEach(name => { + if (hasOwn(mpComponentOptions, name)) { + vueComponentOptions[LIFECYCLE[name]] = mpComponentOptions[name] + } + }) } diff --git a/src/core/runtime/wrapper/create-vue-component/parser/lifetimes-parser.js b/src/core/runtime/wrapper/create-vue-component/parser/lifetimes-parser.js index 945013fda..0a93da1db 100644 --- a/src/core/runtime/wrapper/create-vue-component/parser/lifetimes-parser.js +++ b/src/core/runtime/wrapper/create-vue-component/parser/lifetimes-parser.js @@ -1,5 +1,10 @@ +import { + parseLifecycle +} from './lifecycle-parser' + export function parseLifetimes (lifetimes, vueComponentOptions) { if (!lifetimes) { - + return } + parseLifecycle(lifetimes, vueComponentOptions) } diff --git a/src/core/runtime/wrapper/create-vue-component/parser/options-parser.js b/src/core/runtime/wrapper/create-vue-component/parser/options-parser.js index c7eb54da1..daea4c4d1 100644 --- a/src/core/runtime/wrapper/create-vue-component/parser/options-parser.js +++ b/src/core/runtime/wrapper/create-vue-component/parser/options-parser.js @@ -1,5 +1,6 @@ export function parseOptions (options, vueComponentOptions) { if (!options) { - + return } + vueComponentOptions.mpOptions = options } diff --git a/src/core/runtime/wrapper/create-vue-component/parser/relations-parser.js b/src/core/runtime/wrapper/create-vue-component/parser/relations-parser.js index b786d03a7..4656b4380 100644 --- a/src/core/runtime/wrapper/create-vue-component/parser/relations-parser.js +++ b/src/core/runtime/wrapper/create-vue-component/parser/relations-parser.js @@ -1,5 +1,6 @@ export function parseRelations (relations, vueComponentOptions) { if (!relations) { - + return } + vueComponentOptions.mpRelations = relations } diff --git a/src/platforms/app-plus/service/framework/plugins/index.js b/src/platforms/app-plus/service/framework/plugins/index.js index eae90ba10..1386d88db 100644 --- a/src/platforms/app-plus/service/framework/plugins/index.js +++ b/src/platforms/app-plus/service/framework/plugins/index.js @@ -12,6 +12,10 @@ import { initLifecycle } from './lifecycle' +import { + vdSyncCallbacks +} from '../subscribe-handlers/on-vd-sync-callback' + export default { install (Vue, options) { initVue(Vue) @@ -33,5 +37,17 @@ export default { } return oldMount.call(this, el, hydrating) } + + Vue.prototype.$nextTick = function nextTick (cb) { + const renderWatcher = this._watcher + if ( + renderWatcher && + this._$queue.find(watcher => renderWatcher === watcher) + ) { + vdSyncCallbacks.push(cb) + } else { + Vue.nextTick(cb) + } + } } } -- GitLab