提交 1a263626 编写于 作者: DCloud-WZF's avatar DCloud-WZF 💬

wip(uts): vBind

上级 3afbd25f
......@@ -8,11 +8,7 @@ import {
import { createCompilerError, ErrorCodes } from '../errors'
import { camelize } from '@vue/shared'
import { CAMELIZE } from '@vue/compiler-core'
import {
objectExp,
expContentToMapString,
objectStringToMapString,
} from '../utils'
import { objectExp, objectStringToMapString } from '../utils'
import { isString } from '@vue/shared'
// v-bind without arg is handled directly in ./transformElements.ts due to it affecting
......@@ -63,7 +59,7 @@ export const transformBind: DirectiveTransform = (dir, _node, context) => {
}
if ((exp as any).content && objectExp.test((exp as any).content)) {
;(exp as any).content = expContentToMapString(exp)
;(exp as any).content = objectStringToMapString((exp as any).content)
} else if ((exp as any).children) {
// { 'opcity': 1 - (scrollTop * 3 > 100 ? 100 : scrollTop * 3) / 100 } to map
// TODO: 考虑更多边缘情况
......
import { CompilerOptions } from './options'
import {
ExpressionNode,
SimpleExpressionNode,
ConstantTypes,
} from '@vue/compiler-core'
import { isString } from '@vue/shared'
import { isObject, isString } from '@vue/shared'
export function genRenderFunctionDecl({
targetLanguage,
......@@ -15,34 +10,11 @@ export function genRenderFunctionDecl({
}function ${filename}Render(): VNode | null`
}
export function expContentToMapString(exp: ExpressionNode): string {
return objectStringToMapString(
(exp as SimpleExpressionNode).content,
true,
exp
)
}
export const objectExp = /\{[\s\S]*\}/g
export function objectStringToMapString(
content: string,
wrap = true,
exp?: ExpressionNode
): string {
export function objectStringToMapString(content: string, wrap = true): string {
content = content.replace(/\n/g, '')
const matched = content.match(objectExp)![0]
try {
return complexObjectStringToMapString(content, matched, wrap)
} catch (e) {
return simpleObjectSringToMapString(content, matched, wrap, exp)
}
}
function complexObjectStringToMapString(
content: string,
matched: string,
wrap: boolean
): string {
const matchedObj = stringToData(matched)
const matchedObj = stringToData(matched) as Record<any, any>
const mapConstructor = convertObjectToMapString(matchedObj)
return content.replace(
matched,
......@@ -50,99 +22,7 @@ function complexObjectStringToMapString(
)
}
function convertObjectToMapString(obj: Record<any, any>): string {
let result = ''
const keys = Object.keys(obj)
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
if (obj.hasOwnProperty(key)) {
result +=
getKeyValueString(key, obj[key]) + (i === keys.length - 1 ? '' : ', ')
}
}
return `new Map<string, any | null>(${result ? `[${result}]` : ''})`
}
function getKeyValueString(key: string, value: any): string {
value = getValueString(value)
key = hasExtraQuotationMarks(key) || isBooleanString(value) ? key : `'${key}'`
return `[${key}, ${value}]`
}
function getValueString(value: any): string {
if (isString(value)) {
return hasExtraQuotationMarks(value) || isBooleanString(value)
? `${value}`
: `'${value}'`
}
if (Array.isArray(value)) {
return getArrayString(value)
}
if (Object.prototype.toString.call(value) === '[object Object]') {
return convertObjectToMapString(value)
}
return value
}
function getArrayString(arr: any[]): string {
let result = ''
arr.forEach((item, index) => {
result +=
index !== arr.length - 1
? `${getValueString(item)}, `
: getValueString(item)
})
return `[${result}]`
}
function simpleObjectSringToMapString(
content: string,
matched: string,
wrap: boolean,
exp?: ExpressionNode
): string {
const keyValues = matched.replace(/\{|\}/g, '').split(',')
let mapConstructor = ''
keyValues.forEach((keyValue: string, index: number) => {
const colonIndex = keyValue.indexOf(':')
const key =
exp && needAddQuotes(exp, keyValue)
? `'${keyValue.substring(0, colonIndex)}'`
: keyValue.substring(0, colonIndex)
const value = keyValue.substring(colonIndex + 1)
if (key && value) {
mapConstructor += `[${key},${value}]`
if (index < keyValues.length - 1) {
mapConstructor += ','
}
}
})
return content.replace(
matched,
wrap
? `new Map<string, any | null>(${
mapConstructor ? `[${mapConstructor}]` : ''
})`
: mapConstructor
)
}
function needAddQuotes(exp: ExpressionNode, keyValue: string): boolean {
return (
(exp as SimpleExpressionNode).constType === ConstantTypes.CAN_STRINGIFY &&
!hasExtraStartQuotationMarks(keyValue)
)
}
function removeMapWrap(content: string): string {
if (content === 'new Map<string, any | null>()') {
return ''
}
const mapPrefixLength = 29 // new Map<string, any | null>([
return content.substring(mapPrefixLength, content.length - 2)
}
function stringToData(str: string): any {
function stringToData(str: string): object | any[] | string {
str = str.trim()
if (str.startsWith('{')) {
return stringToObject(removeStartAndEndChar(str))
......@@ -229,6 +109,59 @@ function stringToArray(str: string) {
return result
}
function convertObjectToMapString(obj: Record<any, any>): string {
let result = ''
const keys = Object.keys(obj)
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
if (obj.hasOwnProperty(key)) {
result +=
getKeyValueString(key, obj[key]) + (i === keys.length - 1 ? '' : ', ')
}
}
return `new Map<string, any | null>(${result ? `[${result}]` : ''})`
}
function getKeyValueString(key: string, value: any): string {
value = getValueString(value)
key = hasExtraQuotationMarks(key) || isBooleanString(value) ? key : `'${key}'`
return `[${key}, ${value}]`
}
function getValueString(value: any): string {
if (isString(value)) {
return hasExtraQuotationMarks(value) || isBooleanString(value)
? `${value}`
: `'${value}'`
}
if (Array.isArray(value)) {
return getArrayString(value)
}
if (isObject(value)) {
return convertObjectToMapString(value)
}
return value
}
function getArrayString(arr: any[]): string {
let result = ''
arr.forEach((item, index) => {
result +=
index !== arr.length - 1
? `${getValueString(item)}, `
: getValueString(item)
})
return `[${result}]`
}
function removeMapWrap(content: string): string {
if (content === 'new Map<string, any | null>()') {
return ''
}
const mapPrefixLength = 29 // new Map<string, any | null>([
return content.substring(mapPrefixLength, content.length - 2)
}
function hasExtraQuotationMarks(str: string) {
return str.startsWith("'") || str.endsWith("'")
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册