From 8d010067678cd549e1957cdad38e3b48d9805111 Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 6 Sep 2017 03:01:54 -0400 Subject: [PATCH 01/15] refactor(compiler): move postTransforms to after children are processed --- flow/compiler.js | 3 +++ src/compiler/parser/index.js | 9 +++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/flow/compiler.js b/flow/compiler.js index 89473789b00..1837b85af61 100644 --- a/flow/compiler.js +++ b/flow/compiler.js @@ -36,9 +36,12 @@ declare type CompiledResult = { }; declare type ModuleOptions = { + // transform an AST node before any attributes are processed // returning an ASTElement from pre/transforms replaces the element preTransformNode: (el: ASTElement) => ?ASTElement; + // transform an AST node after built-ins like v-if, v-for are processed transformNode: (el: ASTElement) => ?ASTElement; + // transform an AST node after its children have been processed // cannot return replacement in postTransform because tree is already finalized postTransformNode: (el: ASTElement) => void; genData: (el: ASTElement) => string; // generate extra data string for an element diff --git a/src/compiler/parser/index.js b/src/compiler/parser/index.js index 5aeed3e222e..0a6e33c881a 100644 --- a/src/compiler/parser/index.js +++ b/src/compiler/parser/index.js @@ -212,10 +212,6 @@ export function parse ( } else { endPre(element) } - // apply post-transforms - for (let i = 0; i < postTransforms.length; i++) { - postTransforms[i](element, options) - } }, end () { @@ -229,6 +225,11 @@ export function parse ( stack.length -= 1 currentParent = stack[stack.length - 1] endPre(element) + + // apply post-transforms + for (let i = 0; i < postTransforms.length; i++) { + postTransforms[i](element, options) + } }, chars (text: string) { From d45fddce800e5460707032593383e19022109179 Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 6 Sep 2017 05:34:58 -0400 Subject: [PATCH 02/15] feat(weex): recycle-list support WIP --- flow/compiler.js | 1 + src/compiler/parser/index.js | 26 +++++------ src/compiler/parser/text-parser.js | 22 +++++++-- src/platforms/web/compiler/modules/class.js | 4 +- src/platforms/web/compiler/modules/style.js | 4 +- src/platforms/weex/compiler/modules/class.js | 2 +- src/platforms/weex/compiler/modules/index.js | 2 + .../compiler/modules/recycle-list/index.js | 46 +++++++++++++++++++ src/platforms/weex/compiler/modules/style.js | 2 +- 9 files changed, 85 insertions(+), 24 deletions(-) create mode 100644 src/platforms/weex/compiler/modules/recycle-list/index.js diff --git a/flow/compiler.js b/flow/compiler.js index 1837b85af61..25f151943a1 100644 --- a/flow/compiler.js +++ b/flow/compiler.js @@ -154,6 +154,7 @@ declare type ASTExpression = { type: 2; expression: string; text: string; + tokens: Array; static?: boolean; // 2.4 ssr optimization ssrOptimizability?: number; diff --git a/src/compiler/parser/index.js b/src/compiler/parser/index.js index 0a6e33c881a..e352c4b24f0 100644 --- a/src/compiler/parser/index.js +++ b/src/compiler/parser/index.js @@ -90,7 +90,7 @@ export function parse ( } } - function endPre (element) { + function closeElement (element) { // check pre state if (element.pre) { inVPre = false @@ -98,6 +98,10 @@ export function parse ( if (platformIsPreTag(element.tag)) { inPre = false } + // apply post-transforms + for (let i = 0; i < postTransforms.length; i++) { + postTransforms[i](element, options) + } } parseHTML(template, { @@ -210,7 +214,7 @@ export function parse ( currentParent = element stack.push(element) } else { - endPre(element) + closeElement(element) } }, @@ -224,12 +228,7 @@ export function parse ( // pop stack stack.length -= 1 currentParent = stack[stack.length - 1] - endPre(element) - - // apply post-transforms - for (let i = 0; i < postTransforms.length; i++) { - postTransforms[i](element, options) - } + closeElement(element) }, chars (text: string) { @@ -261,11 +260,12 @@ export function parse ( // only preserve whitespace if its not right after a starting tag : preserveWhitespace && children.length ? ' ' : '' if (text) { - let expression - if (!inVPre && text !== ' ' && (expression = parseText(text, delimiters))) { + let res + if (!inVPre && text !== ' ' && (res = parseText(text, delimiters))) { children.push({ type: 2, - expression, + expression: res.expression, + tokens: res.tokens, text }) } else if (text !== ' ' || !children.length || children[children.length - 1].text !== ' ') { @@ -544,8 +544,8 @@ function processAttrs (el) { } else { // literal attribute if (process.env.NODE_ENV !== 'production') { - const expression = parseText(value, delimiters) - if (expression) { + const res = parseText(value, delimiters) + if (res) { warn( `${name}="${value}": ` + 'Interpolation inside attributes has been removed. ' + diff --git a/src/compiler/parser/text-parser.js b/src/compiler/parser/text-parser.js index 10613d11e0c..284fca33bf4 100644 --- a/src/compiler/parser/text-parser.js +++ b/src/compiler/parser/text-parser.js @@ -12,30 +12,42 @@ const buildRegex = cached(delimiters => { return new RegExp(open + '((?:.|\\n)+?)' + close, 'g') }) +type TextParseResult = { + expression: string, + tokens: Array +} + export function parseText ( text: string, delimiters?: [string, string] -): string | void { +): TextParseResult | void { const tagRE = delimiters ? buildRegex(delimiters) : defaultTagRE if (!tagRE.test(text)) { return } const tokens = [] + const rawTokens = [] let lastIndex = tagRE.lastIndex = 0 - let match, index + let match, index, tokenValue while ((match = tagRE.exec(text))) { index = match.index // push text token if (index > lastIndex) { - tokens.push(JSON.stringify(text.slice(lastIndex, index))) + rawTokens.push(tokenValue = text.slice(lastIndex, index)) + tokens.push(JSON.stringify(tokenValue)) } // tag token const exp = parseFilters(match[1].trim()) tokens.push(`_s(${exp})`) + rawTokens.push({ '@binding': exp }) lastIndex = index + match[0].length } if (lastIndex < text.length) { - tokens.push(JSON.stringify(text.slice(lastIndex))) + rawTokens.push(tokenValue = text.slice(lastIndex)) + tokens.push(JSON.stringify(tokenValue)) + } + return { + expression: tokens.join('+'), + tokens: rawTokens } - return tokens.join('+') } diff --git a/src/platforms/web/compiler/modules/class.js b/src/platforms/web/compiler/modules/class.js index eb93895fb43..ffdca250991 100644 --- a/src/platforms/web/compiler/modules/class.js +++ b/src/platforms/web/compiler/modules/class.js @@ -11,8 +11,8 @@ function transformNode (el: ASTElement, options: CompilerOptions) { const warn = options.warn || baseWarn const staticClass = getAndRemoveAttr(el, 'class') if (process.env.NODE_ENV !== 'production' && staticClass) { - const expression = parseText(staticClass, options.delimiters) - if (expression) { + const res = parseText(staticClass, options.delimiters) + if (res) { warn( `class="${staticClass}": ` + 'Interpolation inside attributes has been removed. ' + diff --git a/src/platforms/web/compiler/modules/style.js b/src/platforms/web/compiler/modules/style.js index 425c50540e2..2722b92b44d 100644 --- a/src/platforms/web/compiler/modules/style.js +++ b/src/platforms/web/compiler/modules/style.js @@ -14,8 +14,8 @@ function transformNode (el: ASTElement, options: CompilerOptions) { if (staticStyle) { /* istanbul ignore if */ if (process.env.NODE_ENV !== 'production') { - const expression = parseText(staticStyle, options.delimiters) - if (expression) { + const res = parseText(staticStyle, options.delimiters) + if (res) { warn( `style="${staticStyle}": ` + 'Interpolation inside attributes has been removed. ' + diff --git a/src/platforms/weex/compiler/modules/class.js b/src/platforms/weex/compiler/modules/class.js index fe910fd6573..371a08ea2f5 100644 --- a/src/platforms/weex/compiler/modules/class.js +++ b/src/platforms/weex/compiler/modules/class.js @@ -55,7 +55,7 @@ function parseStaticClass (staticClass: ?string, options: CompilerOptions): Stat const result = parseText(name, options.delimiters) if (result) { dynamic = true - return result + return result.expression } return JSON.stringify(name) }) diff --git a/src/platforms/weex/compiler/modules/index.js b/src/platforms/weex/compiler/modules/index.js index ad7879165ae..ac17809e7d4 100644 --- a/src/platforms/weex/compiler/modules/index.js +++ b/src/platforms/weex/compiler/modules/index.js @@ -2,8 +2,10 @@ import klass from './class' import style from './style' import props from './props' import append from './append' +import recycleList from './recycle-list/index' export default [ + recycleList, klass, style, props, diff --git a/src/platforms/weex/compiler/modules/recycle-list/index.js b/src/platforms/weex/compiler/modules/recycle-list/index.js new file mode 100644 index 00000000000..ac3a8f74638 --- /dev/null +++ b/src/platforms/weex/compiler/modules/recycle-list/index.js @@ -0,0 +1,46 @@ +/* @flow */ + +import { addAttr } from 'compiler/helpers' + +let currentRecycleList = null + +function preTransformNode (el: ASTElement) { + if (el.tag === 'recycle-list') { + currentRecycleList = el + } +} + +function transformNode (el: ASTElement) { + if (currentRecycleList) { + // TODO + } +} + +function postTransformNode (el: ASTElement) { + if (currentRecycleList) { + // : transform children text into value attr + if (el.tag === 'text') { + addAttr(el, 'value', genText(el.children[0])) + el.children = [] + el.plain = false + } + } + if (el === currentRecycleList) { + currentRecycleList = null + } +} + +function genText (node) { + const value = node.type === 3 + ? node.text + : node.tokens.length === 1 + ? node.tokens[0] + : node.tokens + return JSON.stringify(value) +} + +export default { + preTransformNode, + transformNode, + postTransformNode +} diff --git a/src/platforms/weex/compiler/modules/style.js b/src/platforms/weex/compiler/modules/style.js index 7c428091e8a..eb3c93a067a 100644 --- a/src/platforms/weex/compiler/modules/style.js +++ b/src/platforms/weex/compiler/modules/style.js @@ -64,7 +64,7 @@ function parseStaticStyle (staticStyle: ?string, options: CompilerOptions): Stat const dynamicValue = parseText(value, options.delimiters) if (dynamicValue) { dynamic = true - return key + ':' + dynamicValue + return key + ':' + dynamicValue.expression } return key + ':' + JSON.stringify(value) }).filter(result => result) From 91b21364bd8dd4eabd295f655d53f78c8a698425 Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 6 Sep 2017 05:48:01 -0400 Subject: [PATCH 03/15] refactor: fix types --- src/platforms/weex/compiler/modules/recycle-list/index.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/platforms/weex/compiler/modules/recycle-list/index.js b/src/platforms/weex/compiler/modules/recycle-list/index.js index ac3a8f74638..1163e4da4a0 100644 --- a/src/platforms/weex/compiler/modules/recycle-list/index.js +++ b/src/platforms/weex/compiler/modules/recycle-list/index.js @@ -33,9 +33,11 @@ function postTransformNode (el: ASTElement) { function genText (node) { const value = node.type === 3 ? node.text - : node.tokens.length === 1 - ? node.tokens[0] - : node.tokens + : node.type === 2 + ? node.tokens.length === 1 + ? node.tokens[0] + : node.tokens + : '' return JSON.stringify(value) } From 227a2299bd2211920bd0195c8ac1ba5ace596c0e Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 6 Sep 2017 05:57:00 -0400 Subject: [PATCH 04/15] feat(weex): split text into separate module --- .../compiler/modules/recycle-list/index.js | 17 ++------------ .../compiler/modules/recycle-list/text.js | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+), 15 deletions(-) create mode 100644 src/platforms/weex/compiler/modules/recycle-list/text.js diff --git a/src/platforms/weex/compiler/modules/recycle-list/index.js b/src/platforms/weex/compiler/modules/recycle-list/index.js index 1163e4da4a0..82cc6e8f605 100644 --- a/src/platforms/weex/compiler/modules/recycle-list/index.js +++ b/src/platforms/weex/compiler/modules/recycle-list/index.js @@ -1,6 +1,6 @@ /* @flow */ -import { addAttr } from 'compiler/helpers' +import { transformText } from './text' let currentRecycleList = null @@ -20,9 +20,7 @@ function postTransformNode (el: ASTElement) { if (currentRecycleList) { // : transform children text into value attr if (el.tag === 'text') { - addAttr(el, 'value', genText(el.children[0])) - el.children = [] - el.plain = false + transformText(el) } } if (el === currentRecycleList) { @@ -30,17 +28,6 @@ function postTransformNode (el: ASTElement) { } } -function genText (node) { - const value = node.type === 3 - ? node.text - : node.type === 2 - ? node.tokens.length === 1 - ? node.tokens[0] - : node.tokens - : '' - return JSON.stringify(value) -} - export default { preTransformNode, transformNode, diff --git a/src/platforms/weex/compiler/modules/recycle-list/text.js b/src/platforms/weex/compiler/modules/recycle-list/text.js new file mode 100644 index 00000000000..a950aff93a9 --- /dev/null +++ b/src/platforms/weex/compiler/modules/recycle-list/text.js @@ -0,0 +1,22 @@ +/* @flow */ + +import { addAttr } from 'compiler/helpers' + +function genText (node: ASTNode) { + const value = node.type === 3 + ? node.text + : node.type === 2 + ? node.tokens.length === 1 + ? node.tokens[0] + : node.tokens + : '' + return JSON.stringify(value) +} + +export function transformText (el: ASTElement) { + // weex can only contain text, so the parser + // always generates a single child. + addAttr(el, 'value', genText(el.children[0])) + el.children = [] + el.plain = false +} From a65cc6e73fb2d407a6f0983699d24da59936a7b5 Mon Sep 17 00:00:00 2001 From: Hanks Date: Sat, 16 Sep 2017 13:13:23 +0800 Subject: [PATCH 05/15] feat($compiler): supports compiling v-bind to the weex native directive in recycle-list --- src/compiler/codegen/index.js | 11 +++++-- src/compiler/helpers.js | 2 +- .../compiler/modules/recycle-list/index.js | 2 ++ .../compiler/modules/recycle-list/text.js | 8 +++-- .../compiler/modules/recycle-list/v-bind.js | 31 +++++++++++++++++++ 5 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 src/platforms/weex/compiler/modules/recycle-list/v-bind.js diff --git a/src/compiler/codegen/index.js b/src/compiler/codegen/index.js index a8c7d4d5e70..add8e6f363e 100644 --- a/src/compiler/codegen/index.js +++ b/src/compiler/codegen/index.js @@ -476,15 +476,22 @@ function genComponent ( })` } -function genProps (props: Array<{ name: string, value: string }>): string { +function genProps (props: Array<{ name: string, value: any }>): string { let res = '' for (let i = 0; i < props.length; i++) { const prop = props[i] - res += `"${prop.name}":${transformSpecialNewlines(prop.value)},` + res += `"${prop.name}":${generateValue(prop.value)},` } return res.slice(0, -1) } +function generateValue (value) { + if (typeof value === 'string') { + return transformSpecialNewlines(value) + } + return JSON.stringify(value) +} + // #3895, #4268 function transformSpecialNewlines (text: string): string { return text diff --git a/src/compiler/helpers.js b/src/compiler/helpers.js index 5c844bd42e0..212acf3be2f 100644 --- a/src/compiler/helpers.js +++ b/src/compiler/helpers.js @@ -19,7 +19,7 @@ export function addProp (el: ASTElement, name: string, value: string) { (el.props || (el.props = [])).push({ name, value }) } -export function addAttr (el: ASTElement, name: string, value: string) { +export function addAttr (el: ASTElement, name: string, value: any) { (el.attrs || (el.attrs = [])).push({ name, value }) } diff --git a/src/platforms/weex/compiler/modules/recycle-list/index.js b/src/platforms/weex/compiler/modules/recycle-list/index.js index 82cc6e8f605..0fe7bb138a3 100644 --- a/src/platforms/weex/compiler/modules/recycle-list/index.js +++ b/src/platforms/weex/compiler/modules/recycle-list/index.js @@ -1,6 +1,7 @@ /* @flow */ import { transformText } from './text' +import { transformVBind } from './v-bind' let currentRecycleList = null @@ -22,6 +23,7 @@ function postTransformNode (el: ASTElement) { if (el.tag === 'text') { transformText(el) } + transformVBind(el) } if (el === currentRecycleList) { currentRecycleList = null diff --git a/src/platforms/weex/compiler/modules/recycle-list/text.js b/src/platforms/weex/compiler/modules/recycle-list/text.js index a950aff93a9..fb72c81b555 100644 --- a/src/platforms/weex/compiler/modules/recycle-list/text.js +++ b/src/platforms/weex/compiler/modules/recycle-list/text.js @@ -16,7 +16,9 @@ function genText (node: ASTNode) { export function transformText (el: ASTElement) { // weex can only contain text, so the parser // always generates a single child. - addAttr(el, 'value', genText(el.children[0])) - el.children = [] - el.plain = false + if (el.children.length) { + addAttr(el, 'value', genText(el.children[0])) + el.children = [] + el.plain = false + } } diff --git a/src/platforms/weex/compiler/modules/recycle-list/v-bind.js b/src/platforms/weex/compiler/modules/recycle-list/v-bind.js new file mode 100644 index 00000000000..62bb0ac6a21 --- /dev/null +++ b/src/platforms/weex/compiler/modules/recycle-list/v-bind.js @@ -0,0 +1,31 @@ +/* @flow */ + +import { getAndRemoveAttr, addAttr } from 'compiler/helpers' + +function isBindingAttr (name) { + return /^(v\-bind)?\:/.test(name) +} + +function parseRealName (name: string): string { + return name.replace(/^(v\-bind)?\:/, '') +} + +export function transformVBind (el: ASTElement) { + if (!el.attrsList.length) { + return + } + el.attrsList.forEach(attr => { + // console.log('is binding attr:', attr.name, isBindingAttr(attr.name)) + if (isBindingAttr(attr.name)) { + const realName: string = parseRealName(attr.name) + const binding = getAndRemoveAttr(el, attr.name) + if (el.attrs) { + el.attrs = el.attrs.filter(at => at.name !== realName) // omit duplicated + } + getAndRemoveAttr(el, realName) + addAttr(el, realName, { '@binding': binding }) + } + }) + el.hasBindings = false + // el.plain = true +} From 62ddbd99381b3856a0747d751cb2f91f1072a560 Mon Sep 17 00:00:00 2001 From: Hanks Date: Sat, 16 Sep 2017 14:59:23 +0800 Subject: [PATCH 06/15] feat(compile): supports compiling v-if to the weex native directive --- flow/compiler.js | 6 ++-- .../compiler/modules/recycle-list/index.js | 4 ++- .../compiler/modules/recycle-list/v-bind.js | 19 +++++------- .../compiler/modules/recycle-list/v-if.js | 29 +++++++++++++++++++ 4 files changed, 42 insertions(+), 16 deletions(-) create mode 100644 src/platforms/weex/compiler/modules/recycle-list/v-if.js diff --git a/flow/compiler.js b/flow/compiler.js index 25f151943a1..af04c7f15be 100644 --- a/flow/compiler.js +++ b/flow/compiler.js @@ -75,8 +75,8 @@ declare type ASTNode = ASTElement | ASTText | ASTExpression; declare type ASTElement = { type: 1; tag: string; - attrsList: Array<{ name: string; value: string }>; - attrsMap: { [key: string]: string | null }; + attrsList: Array<{ name: string; value: any }>; + attrsMap: { [key: string]: any }; parent: ASTElement | void; children: Array; @@ -89,7 +89,7 @@ declare type ASTElement = { hasBindings?: boolean; text?: string; - attrs?: Array<{ name: string; value: string }>; + attrs?: Array<{ name: string; value: any }>; props?: Array<{ name: string; value: string }>; plain?: boolean; pre?: true; diff --git a/src/platforms/weex/compiler/modules/recycle-list/index.js b/src/platforms/weex/compiler/modules/recycle-list/index.js index 0fe7bb138a3..bb9d438d462 100644 --- a/src/platforms/weex/compiler/modules/recycle-list/index.js +++ b/src/platforms/weex/compiler/modules/recycle-list/index.js @@ -2,6 +2,7 @@ import { transformText } from './text' import { transformVBind } from './v-bind' +import { transformVIf } from './v-if' let currentRecycleList = null @@ -14,6 +15,8 @@ function preTransformNode (el: ASTElement) { function transformNode (el: ASTElement) { if (currentRecycleList) { // TODO + transformVIf(el) + transformVBind(el) } } @@ -23,7 +26,6 @@ function postTransformNode (el: ASTElement) { if (el.tag === 'text') { transformText(el) } - transformVBind(el) } if (el === currentRecycleList) { currentRecycleList = null diff --git a/src/platforms/weex/compiler/modules/recycle-list/v-bind.js b/src/platforms/weex/compiler/modules/recycle-list/v-bind.js index 62bb0ac6a21..f7836c8c214 100644 --- a/src/platforms/weex/compiler/modules/recycle-list/v-bind.js +++ b/src/platforms/weex/compiler/modules/recycle-list/v-bind.js @@ -1,31 +1,26 @@ /* @flow */ +import { camelize } from 'shared/util' import { getAndRemoveAttr, addAttr } from 'compiler/helpers' -function isBindingAttr (name) { +function isBindingAttr (name: string): boolean { return /^(v\-bind)?\:/.test(name) } -function parseRealName (name: string): string { - return name.replace(/^(v\-bind)?\:/, '') +function parseAttrName (name: string): string { + return camelize(name.replace(/^(v\-bind)?\:/, '')) } export function transformVBind (el: ASTElement) { - if (!el.attrsList.length) { + if (!el.attrsList || !el.attrsList.length) { return } el.attrsList.forEach(attr => { - // console.log('is binding attr:', attr.name, isBindingAttr(attr.name)) if (isBindingAttr(attr.name)) { - const realName: string = parseRealName(attr.name) + const name: string = parseAttrName(attr.name) const binding = getAndRemoveAttr(el, attr.name) - if (el.attrs) { - el.attrs = el.attrs.filter(at => at.name !== realName) // omit duplicated - } - getAndRemoveAttr(el, realName) - addAttr(el, realName, { '@binding': binding }) + addAttr(el, name, { '@binding': binding }) } }) el.hasBindings = false - // el.plain = true } diff --git a/src/platforms/weex/compiler/modules/recycle-list/v-if.js b/src/platforms/weex/compiler/modules/recycle-list/v-if.js new file mode 100644 index 00000000000..c21f70ad2f7 --- /dev/null +++ b/src/platforms/weex/compiler/modules/recycle-list/v-if.js @@ -0,0 +1,29 @@ +/* @flow */ + +import { getAndRemoveAttr, addAttr } from 'compiler/helpers' + +function isConditionAttr (name: string): boolean { + return /^v\-if|v\-else|v\-else\-if/.test(name) +} + +export function transformVIf (el: ASTElement) { + for (const attr in el.attrsMap) { + if (!isConditionAttr(attr)) { + continue + } + const binding = getAndRemoveAttr(el, attr) + switch (attr) { + case 'v-if': { + addAttr(el, '[[match]]', binding) + el.attrsMap['[[match]]'] = binding + el.attrsList.push({ name: '[[match]]', value: binding }) + delete el.attrsMap[attr] + delete el.if + delete el.ifConditions + break + } + + // TODO: support v-else and v-else-if + } + } +} From 0d66c8171163aab251bb76f1a22cc493b4b411c2 Mon Sep 17 00:00:00 2001 From: Hanks Date: Sat, 16 Sep 2017 15:30:32 +0800 Subject: [PATCH 07/15] feat($compiler): supports compiling v-for to the weex native directive --- .../compiler/modules/recycle-list/index.js | 2 ++ .../compiler/modules/recycle-list/v-for.js | 35 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 src/platforms/weex/compiler/modules/recycle-list/v-for.js diff --git a/src/platforms/weex/compiler/modules/recycle-list/index.js b/src/platforms/weex/compiler/modules/recycle-list/index.js index bb9d438d462..4dd153c5e92 100644 --- a/src/platforms/weex/compiler/modules/recycle-list/index.js +++ b/src/platforms/weex/compiler/modules/recycle-list/index.js @@ -3,6 +3,7 @@ import { transformText } from './text' import { transformVBind } from './v-bind' import { transformVIf } from './v-if' +import { transformVFor } from './v-for' let currentRecycleList = null @@ -16,6 +17,7 @@ function transformNode (el: ASTElement) { if (currentRecycleList) { // TODO transformVIf(el) + transformVFor(el) transformVBind(el) } } diff --git a/src/platforms/weex/compiler/modules/recycle-list/v-for.js b/src/platforms/weex/compiler/modules/recycle-list/v-for.js new file mode 100644 index 00000000000..ab096cfded1 --- /dev/null +++ b/src/platforms/weex/compiler/modules/recycle-list/v-for.js @@ -0,0 +1,35 @@ +/* @flow */ + +import { addAttr } from 'compiler/helpers' + +function isVForAttr (name: string): boolean { + return /^v\-for/.test(name) +} + +export function transformVFor (el: ASTElement) { + for (const attr in el.attrsMap) { + if (!isVForAttr(attr)) { + continue + } + const desc: Object = { + '@expression': el.for, + '@alias': el.alias + } + if (el.iterator1) { + desc['@index'] = el.iterator1 + } + if (el.iterator2) { + desc['@key'] = el.iterator1 + desc['@index'] = el.iterator2 + } + addAttr(el, '[[repeat]]', desc) + el.attrsMap['[[repeat]]'] = desc + el.attrsList.push({ name: '[[repeat]]', value: desc }) + delete el.attrsMap[attr] + delete el.for + delete el.alias + delete el.key + delete el.iterator1 + delete el.iterator2 + } +} From 5933652554bf415faca5d248938d80061539cc04 Mon Sep 17 00:00:00 2001 From: Hanks Date: Sat, 16 Sep 2017 22:43:36 +0800 Subject: [PATCH 08/15] feat($compiler): compile weex native directives in preTransformNode --- src/compiler/parser/index.js | 2 +- .../compiler/modules/recycle-list/index.js | 9 ++-- .../compiler/modules/recycle-list/v-bind.js | 31 +++++++------ .../compiler/modules/recycle-list/v-for.js | 44 +++++++++---------- .../compiler/modules/recycle-list/v-if.js | 30 +++---------- 5 files changed, 49 insertions(+), 67 deletions(-) diff --git a/src/compiler/parser/index.js b/src/compiler/parser/index.js index e352c4b24f0..c03e4e26c4c 100644 --- a/src/compiler/parser/index.js +++ b/src/compiler/parser/index.js @@ -25,7 +25,7 @@ export const forAliasRE = /(.*?)\s+(?:in|of)\s+(.*)/ export const forIteratorRE = /\((\{[^}]*\}|[^,]*),([^,]*)(?:,([^,]*))?\)/ const argRE = /:(.*)$/ -const bindRE = /^:|^v-bind:/ +export const bindRE = /^:|^v-bind:/ const modifierRE = /\.[^.]+/g const decodeHTMLCached = cached(he.decode) diff --git a/src/platforms/weex/compiler/modules/recycle-list/index.js b/src/platforms/weex/compiler/modules/recycle-list/index.js index 4dd153c5e92..f6e67b639ed 100644 --- a/src/platforms/weex/compiler/modules/recycle-list/index.js +++ b/src/platforms/weex/compiler/modules/recycle-list/index.js @@ -11,14 +11,17 @@ function preTransformNode (el: ASTElement) { if (el.tag === 'recycle-list') { currentRecycleList = el } + if (currentRecycleList) { + // TODO + transformVBind(el) + transformVIf(el) + transformVFor(el) + } } function transformNode (el: ASTElement) { if (currentRecycleList) { // TODO - transformVIf(el) - transformVFor(el) - transformVBind(el) } } diff --git a/src/platforms/weex/compiler/modules/recycle-list/v-bind.js b/src/platforms/weex/compiler/modules/recycle-list/v-bind.js index f7836c8c214..425e7f67bf8 100644 --- a/src/platforms/weex/compiler/modules/recycle-list/v-bind.js +++ b/src/platforms/weex/compiler/modules/recycle-list/v-bind.js @@ -1,26 +1,25 @@ /* @flow */ import { camelize } from 'shared/util' -import { getAndRemoveAttr, addAttr } from 'compiler/helpers' - -function isBindingAttr (name: string): boolean { - return /^(v\-bind)?\:/.test(name) -} +import { bindRE } from 'compiler/parser/index' +import { getAndRemoveAttr } from 'compiler/helpers' function parseAttrName (name: string): string { - return camelize(name.replace(/^(v\-bind)?\:/, '')) + return camelize(name.replace(bindRE, '')) } export function transformVBind (el: ASTElement) { - if (!el.attrsList || !el.attrsList.length) { - return - } - el.attrsList.forEach(attr => { - if (isBindingAttr(attr.name)) { - const name: string = parseAttrName(attr.name) - const binding = getAndRemoveAttr(el, attr.name) - addAttr(el, name, { '@binding': binding }) + for (const attr in el.attrsMap) { + if (bindRE.test(attr)) { + const name: string = parseAttrName(attr) + const value = { + '@binding': getAndRemoveAttr(el, attr) + } + delete el.attrsMap[attr] + el.attrsMap[name] = value + el.attrsList.push({ name, value }) + // addAttr(el, name, value) + // el.hasBindings = false } - }) - el.hasBindings = false + } } diff --git a/src/platforms/weex/compiler/modules/recycle-list/v-for.js b/src/platforms/weex/compiler/modules/recycle-list/v-for.js index ab096cfded1..2396e301085 100644 --- a/src/platforms/weex/compiler/modules/recycle-list/v-for.js +++ b/src/platforms/weex/compiler/modules/recycle-list/v-for.js @@ -1,35 +1,31 @@ /* @flow */ -import { addAttr } from 'compiler/helpers' - -function isVForAttr (name: string): boolean { - return /^v\-for/.test(name) -} +import { forAliasRE, forIteratorRE } from 'compiler/parser/index' +import { getAndRemoveAttr } from 'compiler/helpers' export function transformVFor (el: ASTElement) { - for (const attr in el.attrsMap) { - if (!isVForAttr(attr)) { - continue - } + const exp = getAndRemoveAttr(el, 'v-for') + if (!exp) { + return + } + const inMatch = exp.match(forAliasRE) + if (inMatch) { + const alias = inMatch[1].trim() const desc: Object = { - '@expression': el.for, - '@alias': el.alias - } - if (el.iterator1) { - desc['@index'] = el.iterator1 + '@expression': inMatch[2].trim(), + '@alias': alias } - if (el.iterator2) { - desc['@key'] = el.iterator1 - desc['@index'] = el.iterator2 + const iteratorMatch = alias.match(forIteratorRE) + if (iteratorMatch) { + desc['@alias'] = iteratorMatch[1].trim() + desc['@index'] = iteratorMatch[2].trim() + if (iteratorMatch[3]) { + desc['@key'] = iteratorMatch[2].trim() + desc['@index'] = iteratorMatch[3].trim() + } } - addAttr(el, '[[repeat]]', desc) + delete el.attrsMap['v-for'] el.attrsMap['[[repeat]]'] = desc el.attrsList.push({ name: '[[repeat]]', value: desc }) - delete el.attrsMap[attr] - delete el.for - delete el.alias - delete el.key - delete el.iterator1 - delete el.iterator2 } } diff --git a/src/platforms/weex/compiler/modules/recycle-list/v-if.js b/src/platforms/weex/compiler/modules/recycle-list/v-if.js index c21f70ad2f7..673fb09e7f2 100644 --- a/src/platforms/weex/compiler/modules/recycle-list/v-if.js +++ b/src/platforms/weex/compiler/modules/recycle-list/v-if.js @@ -1,29 +1,13 @@ /* @flow */ -import { getAndRemoveAttr, addAttr } from 'compiler/helpers' - -function isConditionAttr (name: string): boolean { - return /^v\-if|v\-else|v\-else\-if/.test(name) -} +import { getAndRemoveAttr } from 'compiler/helpers' export function transformVIf (el: ASTElement) { - for (const attr in el.attrsMap) { - if (!isConditionAttr(attr)) { - continue - } - const binding = getAndRemoveAttr(el, attr) - switch (attr) { - case 'v-if': { - addAttr(el, '[[match]]', binding) - el.attrsMap['[[match]]'] = binding - el.attrsList.push({ name: '[[match]]', value: binding }) - delete el.attrsMap[attr] - delete el.if - delete el.ifConditions - break - } - - // TODO: support v-else and v-else-if - } + const exp = getAndRemoveAttr(el, 'v-if') + if (exp) { + el.attrsMap['[[match]]'] = exp + el.attrsList.push({ name: '[[match]]', value: exp }) + delete el.attrsMap['v-if'] } + // TODO: support v-else and v-else-if } From 9aae7c9768b311ffd5dc87818df3f32d215d9afc Mon Sep 17 00:00:00 2001 From: Hanks Date: Sun, 17 Sep 2017 00:04:05 +0800 Subject: [PATCH 09/15] feat($compiler): supports compiling v-else-if and v-else to the weex native directive --- .../compiler/modules/recycle-list/index.js | 6 +-- .../compiler/modules/recycle-list/v-for.js | 4 +- .../compiler/modules/recycle-list/v-if.js | 43 +++++++++++++++++-- 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/platforms/weex/compiler/modules/recycle-list/index.js b/src/platforms/weex/compiler/modules/recycle-list/index.js index f6e67b639ed..323df23ae87 100644 --- a/src/platforms/weex/compiler/modules/recycle-list/index.js +++ b/src/platforms/weex/compiler/modules/recycle-list/index.js @@ -7,15 +7,15 @@ import { transformVFor } from './v-for' let currentRecycleList = null -function preTransformNode (el: ASTElement) { +function preTransformNode (el: ASTElement, options: CompilerOptions) { if (el.tag === 'recycle-list') { currentRecycleList = el } if (currentRecycleList) { // TODO transformVBind(el) - transformVIf(el) - transformVFor(el) + transformVIf(el, options) // and v-else-if and v-else + transformVFor(el, options) } } diff --git a/src/platforms/weex/compiler/modules/recycle-list/v-for.js b/src/platforms/weex/compiler/modules/recycle-list/v-for.js index 2396e301085..29e6c6f5835 100644 --- a/src/platforms/weex/compiler/modules/recycle-list/v-for.js +++ b/src/platforms/weex/compiler/modules/recycle-list/v-for.js @@ -3,7 +3,7 @@ import { forAliasRE, forIteratorRE } from 'compiler/parser/index' import { getAndRemoveAttr } from 'compiler/helpers' -export function transformVFor (el: ASTElement) { +export function transformVFor (el: ASTElement, options: CompilerOptions) { const exp = getAndRemoveAttr(el, 'v-for') if (!exp) { return @@ -27,5 +27,7 @@ export function transformVFor (el: ASTElement) { delete el.attrsMap['v-for'] el.attrsMap['[[repeat]]'] = desc el.attrsList.push({ name: '[[repeat]]', value: desc }) + } else if (process.env.NODE_ENV !== 'production' && options.warn) { + options.warn(`Invalid v-for expression: ${exp}`) } } diff --git a/src/platforms/weex/compiler/modules/recycle-list/v-if.js b/src/platforms/weex/compiler/modules/recycle-list/v-if.js index 673fb09e7f2..f01010a251d 100644 --- a/src/platforms/weex/compiler/modules/recycle-list/v-if.js +++ b/src/platforms/weex/compiler/modules/recycle-list/v-if.js @@ -2,12 +2,47 @@ import { getAndRemoveAttr } from 'compiler/helpers' -export function transformVIf (el: ASTElement) { - const exp = getAndRemoveAttr(el, 'v-if') - if (exp) { +function hasConditionDirective (el: ASTElement): boolean { + for (const attr in el.attrsMap) { + if (/^v\-if|v\-else|v\-else\-if$/.test(attr)) { + return true + } + } + return false +} + +function getPrevMatch (el: ASTElement): any { + if (el.parent && el.parent.children) { + const prev: Object = el.parent.children[el.parent.children.length - 1] + return prev.attrsMap['[[match]]'] + } +} + +export function transformVIf (el: ASTElement, options: CompilerOptions) { + if (hasConditionDirective(el)) { + let exp + const ifExp = getAndRemoveAttr(el, 'v-if') + const elseifExp = getAndRemoveAttr(el, 'v-else-if') + if (ifExp) { + exp = ifExp + } else { + const prevMatch = getPrevMatch(el) + if (prevMatch) { + exp = elseifExp + ? `!(${prevMatch}) && (${elseifExp})` // v-else-if + : `!(${prevMatch})` // v-else + } else if (process.env.NODE_ENV !== 'production' && options.warn) { + options.warn( + `v-${elseifExp ? ('else-if="' + elseifExp + '"') : 'else'} ` + + `used on element <${el.tag}> without corresponding v-if.` + ) + return + } + } el.attrsMap['[[match]]'] = exp el.attrsList.push({ name: '[[match]]', value: exp }) delete el.attrsMap['v-if'] + delete el.attrsMap['v-else-if'] + delete el.attrsMap['v-else'] } - // TODO: support v-else and v-else-if } From fa177c6f88da0022ffc0b9e4f45b9b95d88dda28 Mon Sep 17 00:00:00 2001 From: Hanks Date: Tue, 19 Sep 2017 18:29:26 +0800 Subject: [PATCH 10/15] feat($event): support binding parameters on event handler within weex recycle-list --- src/core/vdom/helpers/update-listeners.js | 16 +++++++++++----- src/platforms/weex/entry-framework.js | 4 ++-- src/platforms/weex/runtime/modules/events.js | 6 ++++-- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/core/vdom/helpers/update-listeners.js b/src/core/vdom/helpers/update-listeners.js index d587eecf38a..6b92f5da6de 100644 --- a/src/core/vdom/helpers/update-listeners.js +++ b/src/core/vdom/helpers/update-listeners.js @@ -1,13 +1,15 @@ /* @flow */ import { warn } from 'core/util/index' -import { cached, isUndef } from 'shared/util' +import { cached, isUndef, isPlainObject } from 'shared/util' const normalizeEvent = cached((name: string): { name: string, once: boolean, capture: boolean, - passive: boolean + passive: boolean, + handler?: Function, + params?: Array } => { const passive = name.charAt(0) === '&' name = passive ? name.slice(1) : name @@ -47,11 +49,15 @@ export function updateListeners ( remove: Function, vm: Component ) { - let name, cur, old, event + let name, def, cur, old, event for (name in on) { - cur = on[name] + def = cur = on[name] old = oldOn[name] event = normalizeEvent(name) + if (isPlainObject(def)) { + cur = def.handler + event.params = def.params + } if (isUndef(cur)) { process.env.NODE_ENV !== 'production' && warn( `Invalid handler for event "${event.name}": got ` + String(cur), @@ -61,7 +67,7 @@ export function updateListeners ( if (isUndef(cur.fns)) { cur = on[name] = createFnInvoker(cur) } - add(event.name, cur, event.once, event.capture, event.passive) + add(event.name, cur, event.once, event.capture, event.passive, event.params) } else if (cur !== old) { old.fns = cur on[name] = old diff --git a/src/platforms/weex/entry-framework.js b/src/platforms/weex/entry-framework.js index 9b7c920cfbd..e6491eea607 100644 --- a/src/platforms/weex/entry-framework.js +++ b/src/platforms/weex/entry-framework.js @@ -126,10 +126,10 @@ const jsHandlers = { } } -function fireEvent (instance, nodeId, type, e, domChanges) { +function fireEvent (instance, nodeId, type, e, domChanges, params) { const el = instance.document.getRef(nodeId) if (el) { - return instance.document.fireEvent(el, type, e, domChanges) + return instance.document.fireEvent(el, type, e, domChanges, params) } return new Error(`invalid element reference "${nodeId}"`) } diff --git a/src/platforms/weex/runtime/modules/events.js b/src/platforms/weex/runtime/modules/events.js index 824f08e6154..bb642f60030 100755 --- a/src/platforms/weex/runtime/modules/events.js +++ b/src/platforms/weex/runtime/modules/events.js @@ -8,7 +8,9 @@ function add ( event: string, handler: Function, once: boolean, - capture: boolean + capture: boolean, + passive?: boolean, + params?: Array ) { if (capture) { console.log('Weex do not support event in bubble phase.') @@ -26,7 +28,7 @@ function add ( } } } - target.addEvent(event, handler) + target.addEvent(event, handler, params) } function remove ( From 6afbb2e462dd00bd19ec1c60737a1a16ab05a79e Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 9 Oct 2017 17:47:11 -0400 Subject: [PATCH 11/15] refactor: mark weex-specific block --- src/core/vdom/helpers/update-listeners.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/vdom/helpers/update-listeners.js b/src/core/vdom/helpers/update-listeners.js index 6b92f5da6de..4ec3bf2026f 100644 --- a/src/core/vdom/helpers/update-listeners.js +++ b/src/core/vdom/helpers/update-listeners.js @@ -54,7 +54,8 @@ export function updateListeners ( def = cur = on[name] old = oldOn[name] event = normalizeEvent(name) - if (isPlainObject(def)) { + // $flow-disable-line + if (__WEEX__ && isPlainObject(def)) { cur = def.handler event.params = def.params } From 0113093a1fb19834bda9b9186a94b013876ecce4 Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 9 Oct 2017 21:31:03 -0400 Subject: [PATCH 12/15] feat(wip): recycle list template inline expand --- src/core/vdom/create-component.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/core/vdom/create-component.js b/src/core/vdom/create-component.js index d3de4fb4c20..3dad4ee79a3 100644 --- a/src/core/vdom/create-component.js +++ b/src/core/vdom/create-component.js @@ -144,6 +144,22 @@ export function createComponent ( data = data || {} + // recycle-list optimized render function for extracting cell-slot + // template. This is essentailly inline expanding instead of creating + // an actual instance. + // https://github.com/Hanks10100/weex-native-directive/tree/master/component + // $flow-disable-line + if (__WEEX__ && data.attrs['@isInRecycleList']) { + const altRender = Ctor.options['@render'] + if (altRender) { + return altRender.call( + context, + context.$createElement, + data.attrs + ) + } + } + // resolve constructor options in case global mixins are applied after // component constructor creation resolveConstructorOptions(Ctor) From f21043735fe7378990c775cfa6a4a8f5fac0547a Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 9 Oct 2017 23:11:30 -0400 Subject: [PATCH 13/15] build: add weex factory dev script --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 9cd52f50efc..7d9033a3e35 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,8 @@ "dev:test": "karma start test/unit/karma.dev.config.js", "dev:ssr": "rollup -w -c build/config.js --environment TARGET:web-server-renderer", "dev:compiler": "rollup -w -c build/config.js --environment TARGET:web-compiler ", - "dev:weex": "rollup -w -c build/config.js --environment TARGET:weex-framework ", + "dev:weex": "rollup -w -c build/config.js --environment TARGET:weex-framework", + "dev:weex:factory": "rollup -w -c build/config.js --environment TARGET:weex-factory", "dev:weex:compiler": "rollup -w -c build/config.js --environment TARGET:weex-compiler ", "build": "node build/build.js", "build:ssr": "npm run build -- web-runtime-cjs,web-server-renderer", From 42cf346d7ca24d4d061accfb303f9097784cfcf3 Mon Sep 17 00:00:00 2001 From: Hanks Date: Tue, 24 Oct 2017 01:45:48 +0800 Subject: [PATCH 14/15] feat($compiler): support to compile "v-on" into weex native directive --- flow/compiler.js | 1 + src/compiler/codegen/events.js | 30 +++++++++++++++++-- src/core/vdom/create-component.js | 4 +-- .../compiler/modules/recycle-list/index.js | 2 ++ .../compiler/modules/recycle-list/v-on.js | 25 ++++++++++++++++ 5 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 src/platforms/weex/compiler/modules/recycle-list/v-on.js diff --git a/flow/compiler.js b/flow/compiler.js index af04c7f15be..3143650a828 100644 --- a/flow/compiler.js +++ b/flow/compiler.js @@ -55,6 +55,7 @@ declare type ASTIfConditions = Array; declare type ASTElementHandler = { value: string; + params?: Array; modifiers: ?ASTModifiers; }; diff --git a/src/compiler/codegen/events.js b/src/compiler/codegen/events.js index b15d93160d3..bc8963dffbd 100644 --- a/src/compiler/codegen/events.js +++ b/src/compiler/codegen/events.js @@ -57,6 +57,21 @@ export function genHandlers ( return res.slice(0, -1) + '}' } +// Generate handler code with binding params onn Weex +function genWeexHandler (params: Array, handlerCode: string) { + const wrapperArgs = params.filter(exp => simplePathRE.test(exp)) + const handlerParams = params.map(exp => { + if (simplePathRE.test(exp)) { + return { '@binding': exp } + } + return exp + }) + return '{' + + `handler:function(${wrapperArgs.join(',')},$event){${handlerCode}},\n` + + `params:${JSON.stringify(handlerParams)}` + + '}' +} + function genHandler ( name: string, handler: ASTElementHandler | Array @@ -73,9 +88,14 @@ function genHandler ( const isFunctionExpression = fnExpRE.test(handler.value) if (!handler.modifiers) { - return isMethodPath || isFunctionExpression - ? handler.value - : `function($event){${handler.value}}` // inline statement + if (isMethodPath || isFunctionExpression) { + return handler.value + } + // $flow-disable-line + if (__WEEX__ && handler.params) { + return genWeexHandler(handler.params, handler.value) + } + return `function($event){${handler.value}}` // inline statement } else { let code = '' let genModifierCode = '' @@ -111,6 +131,10 @@ function genHandler ( : isFunctionExpression ? `(${handler.value})($event)` : handler.value + // $flow-disable-line + if (__WEEX__ && handler.params) { + return genWeexHandler(handler.params, code + handlerCode) + } return `function($event){${code}${handlerCode}}` } } diff --git a/src/core/vdom/create-component.js b/src/core/vdom/create-component.js index 3dad4ee79a3..c5e7ee64026 100644 --- a/src/core/vdom/create-component.js +++ b/src/core/vdom/create-component.js @@ -145,11 +145,11 @@ export function createComponent ( data = data || {} // recycle-list optimized render function for extracting cell-slot - // template. This is essentailly inline expanding instead of creating + // template. This is essentially inline expanding instead of creating // an actual instance. // https://github.com/Hanks10100/weex-native-directive/tree/master/component // $flow-disable-line - if (__WEEX__ && data.attrs['@isInRecycleList']) { + if (__WEEX__ && data.attrs && data.attrs['@isInRecycleList']) { const altRender = Ctor.options['@render'] if (altRender) { return altRender.call( diff --git a/src/platforms/weex/compiler/modules/recycle-list/index.js b/src/platforms/weex/compiler/modules/recycle-list/index.js index 323df23ae87..a492e73aae0 100644 --- a/src/platforms/weex/compiler/modules/recycle-list/index.js +++ b/src/platforms/weex/compiler/modules/recycle-list/index.js @@ -4,6 +4,7 @@ import { transformText } from './text' import { transformVBind } from './v-bind' import { transformVIf } from './v-if' import { transformVFor } from './v-for' +import { postTransformVOn } from './v-on' let currentRecycleList = null @@ -31,6 +32,7 @@ function postTransformNode (el: ASTElement) { if (el.tag === 'text') { transformText(el) } + postTransformVOn(el) } if (el === currentRecycleList) { currentRecycleList = null diff --git a/src/platforms/weex/compiler/modules/recycle-list/v-on.js b/src/platforms/weex/compiler/modules/recycle-list/v-on.js new file mode 100644 index 00000000000..347d8d3c7c8 --- /dev/null +++ b/src/platforms/weex/compiler/modules/recycle-list/v-on.js @@ -0,0 +1,25 @@ +/* @flow */ + +const 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: ASTElementHandler) { + const res = inlineStatementRE.exec(handler.value) + if (res && res[2]) { + handler.params = res[2].split(/\s*,\s*/) + } +} + +export function postTransformVOn (el: ASTElement) { + const events: ASTElementHandlers | void = el.events + if (!events) { + return + } + for (const name in events) { + const handler: ASTElementHandler | Array = events[name] + if (Array.isArray(handler)) { + handler.map(fn => parseHandlerParams(fn)) + } else { + parseHandlerParams(handler) + } + } +} From 900e20ab4e2ce473baa98e7ee028bbd9b69d1bda Mon Sep 17 00:00:00 2001 From: Hanks Date: Fri, 27 Oct 2017 17:12:53 +0800 Subject: [PATCH 15/15] feat($compiler): adjust handler params to fit the weex native renderer + Filter the non-expression params and the `$event`. + Use `$event` as the last argument of handler. --- src/compiler/codegen/events.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/compiler/codegen/events.js b/src/compiler/codegen/events.js index bc8963dffbd..ec8f724da66 100644 --- a/src/compiler/codegen/events.js +++ b/src/compiler/codegen/events.js @@ -57,17 +57,13 @@ export function genHandlers ( return res.slice(0, -1) + '}' } -// Generate handler code with binding params onn Weex +// Generate handler code with binding params on Weex function genWeexHandler (params: Array, handlerCode: string) { - const wrapperArgs = params.filter(exp => simplePathRE.test(exp)) - const handlerParams = params.map(exp => { - if (simplePathRE.test(exp)) { - return { '@binding': exp } - } - return exp - }) + const wrapperArgs = params.filter(exp => simplePathRE.test(exp) && exp !== '$event') + const handlerParams = wrapperArgs.map(exp => ({ '@binding': exp })) + wrapperArgs.push('$event') return '{' + - `handler:function(${wrapperArgs.join(',')},$event){${handlerCode}},\n` + + `handler:function(${wrapperArgs.join(',')}){${handlerCode}},\n` + `params:${JSON.stringify(handlerParams)}` + '}' }