UNPKG

vue

Version:

Reactive, component-oriented view layer for modern web interfaces.

134 lines (118 loc) 2.85 kB
/* @flow */ /** * Cross-platform code generation for component v-model */ export function genComponentModel ( el: ASTElement, value: string, modifiers: ?ASTModifiers ): ?boolean { const { number, trim } = modifiers || {} const baseValueExpression = '$$v' let valueExpression = baseValueExpression if (trim) { valueExpression = `(typeof ${baseValueExpression} === 'string'` + `? ${baseValueExpression}.trim()` + `: ${baseValueExpression})` } if (number) { valueExpression = `_n(${valueExpression})` } const assignment = genAssignmentCode(value, valueExpression) el.model = { value: `(${value})`, expression: `"${value}"`, callback: `function (${baseValueExpression}) {${assignment}}` } } /** * Cross-platform codegen helper for generating v-model value assignment code. */ export function genAssignmentCode ( value: string, assignment: string ): string { const modelRs = parseModel(value) if (modelRs.idx === null) { return `${value}=${assignment}` } else { return `var $$exp = ${modelRs.exp}, $$idx = ${modelRs.idx};` + `if (!Array.isArray($$exp)){` + `${value}=${assignment}}` + `else{$$exp.splice($$idx, 1, ${assignment})}` } } /** * parse directive model to do the array update transform. a[idx] = val => $$a.splice($$idx, 1, val) * * for loop possible cases: * * - test * - test[idx] * - test[test1[idx]] * - test["a"][idx] * - xxx.test[a[a].test1[idx]] * - test.xxx.a["asa"][test1[idx]] * */ let len, str, chr, index, expressionPos, expressionEndPos export function parseModel (val: string): Object { str = val len = str.length index = expressionPos = expressionEndPos = 0 if (val.indexOf('[') < 0 || val.lastIndexOf(']') < len - 1) { return { exp: val, idx: null } } while (!eof()) { chr = next() /* istanbul ignore if */ if (isStringStart(chr)) { parseString(chr) } else if (chr === 0x5B) { parseBracket(chr) } } return { exp: val.substring(0, expressionPos), idx: val.substring(expressionPos + 1, expressionEndPos) } } function next (): number { return str.charCodeAt(++index) } function eof (): boolean { return index >= len } function isStringStart (chr: number): boolean { return chr === 0x22 || chr === 0x27 } function parseBracket (chr: number): void { let inBracket = 1 expressionPos = index while (!eof()) { chr = next() if (isStringStart(chr)) { parseString(chr) continue } if (chr === 0x5B) inBracket++ if (chr === 0x5D) inBracket-- if (inBracket === 0) { expressionEndPos = index break } } } function parseString (chr: number): void { const stringQuote = chr while (!eof()) { chr = next() if (chr === stringQuote) { break } } }