From d6127e3049da7483063a40a2f8a8695043487472 Mon Sep 17 00:00:00 2001 From: fxy060608 Date: Tue, 10 Sep 2019 13:54:17 +0800 Subject: [PATCH] feat(app-plus-nvue): recycle-list --- packages/uni-app-plus-nvue/dist/index.js | 6 +- .../uni-app-plus-nvue/dist/index.legacy.js | 112 ++++- .../packages/weex-template-compiler/build.js | 386 ++++++++---------- .../service/api/ui/pull-down-refresh.js | 6 +- 4 files changed, 279 insertions(+), 231 deletions(-) diff --git a/packages/uni-app-plus-nvue/dist/index.js b/packages/uni-app-plus-nvue/dist/index.js index 56f43d327..91cb12a79 100644 --- a/packages/uni-app-plus-nvue/dist/index.js +++ b/packages/uni-app-plus-nvue/dist/index.js @@ -327,7 +327,11 @@ var serviceContext = (function () { let webview; function setPullDownRefreshPageId (pullDownRefreshWebview) { - webview = pullDownRefreshWebview; + if (typeof pullDownRefreshWebview === 'number') { + webview = plus.webview.getWebviewById(String(pullDownRefreshWebview)); + } else { + webview = pullDownRefreshWebview; + } } function startPullDownRefresh () { diff --git a/packages/uni-app-plus-nvue/dist/index.legacy.js b/packages/uni-app-plus-nvue/dist/index.legacy.js index 29b9757b9..b51547c3d 100644 --- a/packages/uni-app-plus-nvue/dist/index.legacy.js +++ b/packages/uni-app-plus-nvue/dist/index.legacy.js @@ -10,19 +10,100 @@ try { window.addEventListener('test-passive', null, opts); } catch (e) {} +const _toString = Object.prototype.toString; const hasOwnProperty = Object.prototype.hasOwnProperty; function isFn (fn) { return typeof fn === 'function' } +function isPlainObject (obj) { + return _toString.call(obj) === '[object Object]' +} + function hasOwn (obj, key) { return hasOwnProperty.call(obj, key) } +const HOOKS = [ + 'invoke', + 'success', + 'fail', + 'complete', + 'returnValue' +]; + const globalInterceptors = {}; const scopedInterceptors = {}; +function mergeHook (parentVal, childVal) { + const res = childVal + ? parentVal + ? parentVal.concat(childVal) + : Array.isArray(childVal) + ? childVal : [childVal] + : parentVal; + return res + ? dedupeHooks(res) + : res +} + +function dedupeHooks (hooks) { + const res = []; + for (let i = 0; i < hooks.length; i++) { + if (res.indexOf(hooks[i]) === -1) { + res.push(hooks[i]); + } + } + return res +} + +function removeHook (hooks, hook) { + const index = hooks.indexOf(hook); + if (index !== -1) { + hooks.splice(index, 1); + } +} + +function mergeInterceptorHook (interceptor, option) { + Object.keys(option).forEach(hook => { + if (HOOKS.indexOf(hook) !== -1 && isFn(option[hook])) { + interceptor[hook] = mergeHook(interceptor[hook], option[hook]); + } + }); +} + +function removeInterceptorHook (interceptor, option) { + if (!interceptor || !option) { + return + } + Object.keys(option).forEach(hook => { + if (HOOKS.indexOf(hook) !== -1 && isFn(option[hook])) { + removeHook(interceptor[hook], option[hook]); + } + }); +} + +function addInterceptor (method, option) { + if (typeof method === 'string' && isPlainObject(option)) { + mergeInterceptorHook(scopedInterceptors[method] || (scopedInterceptors[method] = {}), option); + } else if (isPlainObject(method)) { + mergeInterceptorHook(globalInterceptors, method); + } +} + +function removeInterceptor (method, option) { + if (typeof method === 'string') { + if (isPlainObject(option)) { + removeInterceptorHook(scopedInterceptors[method], option); + } else { + delete scopedInterceptors[method]; + } + } else if (isPlainObject(method)) { + removeInterceptorHook(globalInterceptors, method); + } +} + function wrapperHook (hook) { return function (data) { return hook(data) || data @@ -119,7 +200,20 @@ function invokeApi (method, api, options, ...params) { } } return api(options, ...params) -} +} + +const promiseInterceptor = { + returnValue (res) { + if (!isPromise(res)) { + return res + } + return res.then(res => { + return res[1] + }).catch(res => { + return res[0] + }) + } +}; const SYNC_API_RE = /^\$|getMenuButtonBoundingClientRect|^report|interceptors|Interceptor$|getSubNVueById|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$|base64ToArrayBuffer|arrayBufferToBase64/; @@ -667,6 +761,10 @@ function createLivePusherContext (id, vm) { return new LivePusherContext(id, elm) } +const interceptors = { + promiseInterceptor +}; + var apis = /*#__PURE__*/Object.freeze({ @@ -677,7 +775,10 @@ var apis = /*#__PURE__*/Object.freeze({ $emit: $emit, createMapContext: createMapContext, createVideoContext: createVideoContext, - createLivePusherContext: createLivePusherContext + createLivePusherContext: createLivePusherContext, + interceptors: interceptors, + addInterceptor: addInterceptor, + removeInterceptor: removeInterceptor }); function initUni (uni, nvue, plus, BroadcastChannel) { @@ -710,7 +811,8 @@ function initUni (uni, nvue, plus, BroadcastChannel) { return promisify(name, uni[name]) }, set (target, name, value) { - target[name] = value; + target[name] = value; + return true } }) } @@ -760,8 +862,8 @@ function createInstanceContext () { getUniEmitter () { return getGlobalUniEmitter() }, - getCurrentPages () { - return getGlobalCurrentPages() + getCurrentPages (returnAll) { + return getGlobalCurrentPages(returnAll) } } } diff --git a/packages/vue-cli-plugin-hbuilderx/packages/weex-template-compiler/build.js b/packages/vue-cli-plugin-hbuilderx/packages/weex-template-compiler/build.js index fb0681bf8..be29e6528 100644 --- a/packages/vue-cli-plugin-hbuilderx/packages/weex-template-compiler/build.js +++ b/packages/vue-cli-plugin-hbuilderx/packages/weex-template-compiler/build.js @@ -613,7 +613,7 @@ function parseComponent ( return cumulated }, {}) };// fixed by xxxxxx - if (isSpecialTag(tag) && !isCustomBlock(currentBlock.attrs.lang || '')) { + if (isSpecialTag(tag) && !isCustomBlock(String(currentBlock.attrs.lang || ''))) { checkAttrs(currentBlock, attrs); if (tag === 'style') { sfc.styles.push(currentBlock); @@ -671,7 +671,7 @@ function parseComponent ( } else { var offset = content.slice(0, block.start).split(splitRE).length; var lang = block.attrs && block.attrs.lang; // fixed by xxxxxx - var padChar = block.type === 'script' && !block.lang && !isCustomBlock(lang || '') + var padChar = block.type === 'script' && !block.lang && !isCustomBlock(String(lang || '')) ? '//\n' : '\n'; return Array(offset).join(padChar) @@ -2386,67 +2386,146 @@ function isDirectChildOfTemplateFor (node) { /* */ -var fnExpRE = /^([\w$_]+|\([^)]*?\))\s*=>|^function\s*(?:[\w$]+)?\s*\(/; -var fnInvokeRE = /\([^)]*?\);*$/; -var simplePathRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/; +// import { warn } from 'core/util/index' -// KeyboardEvent.keyCode aliases -var keyCodes = { - esc: 27, - tab: 9, - enter: 13, - space: 32, - up: 38, - left: 37, - right: 39, - down: 40, - 'delete': [8, 46] -}; +// this will be preserved during build +// $flow-disable-line +var acorn = require('acorn'); // $flow-disable-line +var walk = require('acorn/dist/walk'); // $flow-disable-line +var escodegen = require('escodegen'); -// KeyboardEvent.key aliases -var keyNames = { - // #7880: IE11 and Edge use `Esc` for Escape key name. - esc: ['Esc', 'Escape'], - tab: 'Tab', - enter: 'Enter', - // #9112: IE11 uses `Spacebar` for Space key name. - space: [' ', 'Spacebar'], - // #7806: IE11 uses key names without `Arrow` prefix for arrow keys. - up: ['Up', 'ArrowUp'], - left: ['Left', 'ArrowLeft'], - right: ['Right', 'ArrowRight'], - down: ['Down', 'ArrowDown'], - // #9112: IE11 uses `Del` for Delete key name. - 'delete': ['Backspace', 'Delete', 'Del'] -}; +var functionCallRE = /^\s*([A-Za-z_$0-9\['\."\]]+)*\s*\(\s*(([A-Za-z_$0-9\['\."\]]+)?(\s*,\s*([A-Za-z_$0-9\['\."\]]+))*)\s*\)$/; -// #4868: modifiers that prevent the execution of the listener -// need to explicitly return null so that we can determine whether to remove -// the listener for .once -var genGuard = function (condition) { return ("if(" + condition + ")return null;"); }; - -var modifierCode = { - stop: '$event.stopPropagation();', - prevent: '$event.preventDefault();', - self: genGuard("$event.target !== $event.currentTarget"), - ctrl: genGuard("!$event.ctrlKey"), - shift: genGuard("!$event.shiftKey"), - alt: genGuard("!$event.altKey"), - meta: genGuard("!$event.metaKey"), - left: genGuard("'button' in $event && $event.button !== 0"), - middle: genGuard("'button' in $event && $event.button !== 1"), - right: genGuard("'button' in $event && $event.button !== 2") -}; +function nodeToBinding (node) { + switch (node.type) { + case 'Literal': return node.value + case 'Identifier': + case 'UnaryExpression': + case 'BinaryExpression': + case 'LogicalExpression': + case 'ConditionalExpression': + case 'MemberExpression': return { '@binding': escodegen.generate(node) } + case 'ArrayExpression': return node.elements.map(function (_) { return nodeToBinding(_); }) + case 'ObjectExpression': { + var object = {}; + node.properties.forEach(function (prop) { + if (!prop.key || prop.key.type !== 'Identifier') { + return + } + var key = escodegen.generate(prop.key); + var value = nodeToBinding(prop.value); + if (key && value) { + object[key] = value; + } + }); + return object + } + default: { + // warn(`Not support ${node.type}: "${escodegen.generate(node)}"`) + return '' + } + } +} + +function generateBinding (exp) { + if (exp && typeof exp === 'string') { + var ast = null; + try { + ast = acorn.parse(("(" + exp + ")")); + } catch (e) { + // warn(`Failed to parse the expression: "${exp}"`) + return '' + } + + var output = ''; + walk.simple(ast, { + Expression: function Expression (node) { + output = nodeToBinding(node); + } + }); + return output + } +} + +/* */ + +// this will be preserved during build +// $flow-disable-line +var transpile = require('vue-template-es2015-compiler'); + +// Generate handler code with binding params for Weex platform +/* istanbul ignore next */ +function genWeexHandlerWithParams (handlerCode) { + var match = functionCallRE.exec(handlerCode); + if (!match) { + return '' + } + var handlerExp = match[1]; + var params = match[2].split(/\s*,\s*/); + var exps = params.filter(function (exp) { return simplePathRE.test(exp) && exp !== '$event'; }); + var bindings = exps.map(function (exp) { return generateBinding(exp); }); + var args = exps.map(function (exp, index) { + var key = "$$_" + (index + 1); + for (var i = 0; i < params.length; ++i) { + if (params[i] === exp) { + params[i] = key; + } + } + return key + }); + args.push('$event'); + return ("{\n handler: function (" + (args.join(',')) + ") {\n " + handlerExp + "(" + (params.join(',')) + ");\n },\n params:" + (JSON.stringify(bindings)) + "\n }") +} + +function genWeexHandler (handler, options) { + var code = handler.value; + var isMethodPath = simplePathRE.test(code); + var isFunctionExpression = fnExpRE.test(code); + var isFunctionCall = functionCallRE.test(code); + + // TODO: binding this to recyclable event handlers + if (options.recyclable) { + if (isMethodPath) { + return ("function($event){this." + code + "()}") + } + if (isFunctionExpression && options.warn) { + options.warn(("Function expression is not supported in recyclable components: " + code + ".")); + } + if (isFunctionCall) { + return ("function($event){this." + code + "}") + } + // inline statement + code = transpile(("with(this){" + code + "}"), { + transforms: { stripWith: true } + }); + } + + if (isMethodPath || isFunctionExpression) { + return code + } + /* istanbul ignore if */ + if (handler.params) { + return genWeexHandlerWithParams(handler.value) + } + // inline statement + return ("function($event){" + code + "}") +} + +/* */ +var fnExpRE = /^([\w$_]+|\([^)]*?\))\s*=>|^function\s*(?:[\w$]+)?\s*\(/; +var fnInvokeRE = /\([^)]*?\);*$/; +var simplePathRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/; function genHandlers ( events, - isNative + isNative, + options ) { var prefix = isNative ? 'nativeOn:' : 'on:'; var staticHandlers = ""; var dynamicHandlers = ""; for (var name in events) { - var handlerCode = genHandler(events[name]); + var handlerCode = genHandler(events[name], options); if (events[name] && events[name].dynamic) { dynamicHandlers += name + "," + handlerCode + ","; } else { @@ -2461,116 +2540,23 @@ function genHandlers ( } } -// Generate handler code with binding params on Weex -/* istanbul ignore next */ -function genWeexHandler (params, handlerCode) { - var innerHandlerCode = handlerCode; - var exps = params.filter(function (exp) { return simplePathRE.test(exp) && exp !== '$event'; }); - var bindings = exps.map(function (exp) { return ({ '@binding': exp }); }); - var args = exps.map(function (exp, i) { - var key = "$_" + (i + 1); - innerHandlerCode = innerHandlerCode.replace(exp, key); - return key - }); - args.push('$event'); - return '{\n' + - "handler:function(" + (args.join(',')) + "){" + innerHandlerCode + "},\n" + - "params:" + (JSON.stringify(bindings)) + "\n" + - '}' -} - -function genHandler (handler) { +function genHandler (handler, options) { if (!handler) { return 'function(){}' } if (Array.isArray(handler)) { - return ("[" + (handler.map(function (handler) { return genHandler(handler); }).join(',')) + "]") + return ("[" + (handler.map(function (handler) { return genHandler(handler, options); }).join(',')) + "]") } var isMethodPath = simplePathRE.test(handler.value); var isFunctionExpression = fnExpRE.test(handler.value); var isFunctionInvocation = simplePathRE.test(handler.value.replace(fnInvokeRE, '')); - if (!handler.modifiers) { - if (isMethodPath || isFunctionExpression) { - return handler.value - } - /* istanbul ignore if */ - if (handler.params) { - return genWeexHandler(handler.params, handler.value) - } - return ("function($event){" + (isFunctionInvocation ? ("return " + (handler.value)) : handler.value) + "}") // inline statement - } else { - var code = ''; - var genModifierCode = ''; - var keys = []; - for (var key in handler.modifiers) { - if (modifierCode[key]) { - genModifierCode += modifierCode[key]; - // left/right - if (keyCodes[key]) { - keys.push(key); - } - } else if (key === 'exact') { - var modifiers = (handler.modifiers); - genModifierCode += genGuard( - ['ctrl', 'shift', 'alt', 'meta'] - .filter(function (keyModifier) { return !modifiers[keyModifier]; }) - .map(function (keyModifier) { return ("$event." + keyModifier + "Key"); }) - .join('||') - ); - } else { - keys.push(key); - } - } - if (keys.length) { - code += genKeyFilter(keys); - } - // Make sure modifiers like prevent and stop get executed after key filtering - if (genModifierCode) { - code += genModifierCode; - } - var handlerCode = isMethodPath - ? ("return " + (handler.value) + "($event)") - : isFunctionExpression - ? ("return (" + (handler.value) + ")($event)") - : isFunctionInvocation - ? ("return " + (handler.value)) - : handler.value; - /* istanbul ignore if */ - if (handler.params) { - return genWeexHandler(handler.params, code + handlerCode) + // Weex does not support modifiers + { + return genWeexHandler(handler, options) } - return ("function($event){" + code + handlerCode + "}") - } -} - -function genKeyFilter (keys) { - return ( - // make sure the key filters only apply to KeyboardEvents - // #9441: can't use 'keyCode' in $event because Chrome autofill fires fake - // key events that do not have keyCode property... - "if(!$event.type.indexOf('key')&&" + - (keys.map(genFilterCode).join('&&')) + ")return null;" - ) -} - -function genFilterCode (key) { - var keyVal = parseInt(key, 10); - if (keyVal) { - return ("$event.keyCode!==" + keyVal) - } - var keyCode = keyCodes[key]; - var keyName = keyNames[key]; - return ( - "_k($event.keyCode," + - (JSON.stringify(key)) + "," + - (JSON.stringify(keyCode)) + "," + - "$event.key," + - "" + (JSON.stringify(keyName)) + - ")" - ) } var ASSET_TYPES = [ @@ -2846,6 +2832,11 @@ var VNode = function VNode ( componentOptions, asyncFactory ) { + {// fixed by xxxxxx 后续优化 + if(data && Array.isArray(data.class)){ + data.class = data.class.slice(0); + } + } this.tag = tag; this.data = data; this.children = children; @@ -3700,10 +3691,10 @@ function genData (el, state) { } // event handlers if (el.events) { - data += (genHandlers(el.events, false)) + ","; + data += (genHandlers(el.events, false, state.options)) + ","; } if (el.nativeEvents) { - data += (genHandlers(el.nativeEvents, true)) + ","; + data += (genHandlers(el.nativeEvents, true, state.options)) + ","; } // slot target // only for non-scoped slots @@ -4692,6 +4683,15 @@ function postTransformComponentRoot (el) { /* */ +function postTransformRef (el, options) { + if (el.ref) { + addAttr(el, 'ref', el.ref); + delete el.ref; + } +} + +/* */ + function genText$1 (node) { var value = node.type === 3 ? node.text @@ -4714,67 +4714,6 @@ function postTransformText (el) { /* */ -// import { warn } from 'core/util/index' - -// this will be preserved during build -// $flow-disable-line -var acorn = require('acorn'); // $flow-disable-line -var walk = require('acorn/dist/walk'); // $flow-disable-line -var escodegen = require('escodegen'); - -function nodeToBinding (node) { - switch (node.type) { - case 'Literal': return node.value - case 'Identifier': - case 'UnaryExpression': - case 'BinaryExpression': - case 'LogicalExpression': - case 'ConditionalExpression': - case 'MemberExpression': return { '@binding': escodegen.generate(node) } - case 'ArrayExpression': return node.elements.map(function (_) { return nodeToBinding(_); }) - case 'ObjectExpression': { - var object = {}; - node.properties.forEach(function (prop) { - if (!prop.key || prop.key.type !== 'Identifier') { - return - } - var key = escodegen.generate(prop.key); - var value = nodeToBinding(prop.value); - if (key && value) { - object[key] = value; - } - }); - return object - } - default: { - // warn(`Not support ${node.type}: "${escodegen.generate(node)}"`) - return '' - } - } -} - -function generateBinding (exp) { - if (exp && typeof exp === 'string') { - var ast = null; - try { - ast = acorn.parse(("(" + exp + ")")); - } catch (e) { - // warn(`Failed to parse the expression: "${exp}"`) - return '' - } - - var output = ''; - walk.simple(ast, { - Expression: function Expression (node) { - output = nodeToBinding(node); - } - }); - return output - } -} - -/* */ - function parseAttrName (name) { return camelize(name.replace(bindRE, '')) } @@ -4884,10 +4823,8 @@ function preTransformVFor (el, options) { /* */ -var inlineStatementRE = /^\s*([A-Za-z_$0-9\['\."\]]+)*\s*\(\s*(([A-Za-z_$0-9\['\."\]]+)?(\s*,\s*([A-Za-z_$0-9\['\."\]]+))*)\s*\)$/; - function parseHandlerParams (handler) { - var res = inlineStatementRE.exec(handler.value); + var res = functionCallRE.exec(handler.value); if (res && res[2]) { handler.params = res[2].split(/\s*,\s*/); } @@ -4941,10 +4878,10 @@ function preTransformNode$1 (el, options) { currentRecycleList = el; } if (shouldCompile(el, options)) { - preTransformVBind(el); + preTransformVBind(el, options); preTransformVIf(el, options); // also v-else-if and v-else preTransformVFor(el, options); - preTransformVOnce(el); + preTransformVOnce(el, options); } } @@ -4957,12 +4894,13 @@ function postTransformNode (el, options) { // mark child component in parent template postTransformComponent(el, options); // mark root in child component template - postTransformComponentRoot(el); + postTransformComponentRoot(el, options); // : transform children text into value attr - if (el.tag === 'text') { - postTransformText(el); + if (el.tag === 'text' || el.tag === 'u-text') { + postTransformText(el, options); } - postTransformVOn(el); + postTransformVOn(el, options); + postTransformRef(el, options); } if (el === currentRecycleList) { currentRecycleList = null; @@ -5033,7 +4971,7 @@ var directives = { var isReservedTag = makeMap( 'template,script,style,element,content,slot,link,meta,svg,view,' + - 'a,div,img,image,text,span,input,textarea,spinner,select,' + + 'a,div,img,image,text,u-text,span,input,textarea,spinner,select,' + 'slider,slider-neighbor,indicator,canvas,' + 'list,cell,header,loading,loading-indicator,refresh,scrollable,scroller,' + 'video,web,embed,tabbar,tabheader,datepicker,timepicker,marquee,countdown', @@ -5049,7 +4987,7 @@ var canBeLeftOpenTag$1 = makeMap( ); var isRuntimeComponent = makeMap( - 'richtext,transition,transition-group', + 'richtext,transition,transition-group,recycle-list', true ); diff --git a/src/platforms/app-plus/service/api/ui/pull-down-refresh.js b/src/platforms/app-plus/service/api/ui/pull-down-refresh.js index 40b3e4c04..488102083 100644 --- a/src/platforms/app-plus/service/api/ui/pull-down-refresh.js +++ b/src/platforms/app-plus/service/api/ui/pull-down-refresh.js @@ -5,7 +5,11 @@ import { let webview export function setPullDownRefreshPageId (pullDownRefreshWebview) { - webview = pullDownRefreshWebview + if (typeof pullDownRefreshWebview === 'number') { + webview = plus.webview.getWebviewById(String(pullDownRefreshWebview)) + } else { + webview = pullDownRefreshWebview + } } export function startPullDownRefresh () { -- GitLab