Skip to content
21 changes: 19 additions & 2 deletions packages/hap-compiler/src/style/validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -2656,7 +2656,24 @@ const validatorMap = {
starSecondary: validator.url,
// font
fontSrc: validator.fontSrc,
fontFamily: validator.fontFamily
fontFamily: validator.fontFamily,
themeColor: makeEnumValidator([
'uxCardColorTheme',
'uxCardColorAccent',
'uxCardColorPrimary',
'uxCardColorSecondary',
'uxCardColorSecondaryVariant',
'uxCardColorTertiary',
'uxCardColorQuaternary',
'uxCardColorContainer',
'uxCardBackground',
'uxCardColorHue',
'uxCardColorHueSecondary',
'uxIconColorAccent',
'uxIconColorPrimary',
'uxIconColorSecondary',
'uxIconColorBackground'
])
}

/**
Expand All @@ -2672,7 +2689,7 @@ function validate(name, value, options) {
const validator = validatorMap[name]

if (typeof validator === 'function') {
if (typeof value !== 'function') {
if (typeof value !== 'function' && value.indexOf('function') < 0) {
if (mightReferlocalResource(name)) {
result = validator(value, options)
} else {
Expand Down
10 changes: 7 additions & 3 deletions packages/hap-compiler/src/template/exp.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ function trimhtml(str) {
* @param isLite is lite card
* @returns {*}
*/
function transExpr(expContent, toFunc, isLite) {
function transExpr(expContent, toFunc, isLite, isCard) {
let ret
const trimExpContent = expContent.trim()
if (!textParser.isExpr(trimExpContent)) {
Expand Down Expand Up @@ -64,8 +64,12 @@ function transExpr(expContent, toFunc, isLite) {
ret = ret.join(' + ')
if (toFunc !== false) {
try {
/* eslint-disable no-eval */
ret = eval('(function () {return ' + ret + '})')
if (isCard) {
ret = 'function () {return ' + ret + '}'
} else {
/* eslint-disable no-eval */
ret = eval('(function () {return ' + ret + '})')
}
/* eslint-enable no-eval */
} catch (err) {
err.isExpressionError = true
Expand Down
8 changes: 7 additions & 1 deletion packages/hap-compiler/src/template/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,13 @@ function parse(source, options) {
{ treeAdapter: parse5.treeAdapters.default, locationInfo: true },
options.filePath
)
const output = { result: {}, log: [], depFiles: [], isLite: !!options.lite }
const output = {
result: {},
log: [],
depFiles: [],
isCard: !!options.card,
isLite: !!options.lite
}

// 模板为空或解析失败
/* istanbul ignore if */
Expand Down
175 changes: 124 additions & 51 deletions packages/hap-compiler/src/template/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,16 @@ function genCheckboxModel(node, attrName, value, output) {
${expValue} = checked ? ${trueValueBinding} : ${falseValueBinding}
}`

addAttr(output.result, attrName, eval(`(function() {${attrCheckedCode}})`))
addHandler(output.result, 'change', eval(`(function(evt) {${eventChangeCode}})`))

const isCard = output.isCard
const isLite = output.isLite
if (isCard && !isLite) {
addAttr(output.result, attrName, `(function() {${attrCheckedCode}})`)
addAttr(output.result, attrName + 'Raw', value)
addHandler(output.result, 'change', `function(evt) {${eventChangeCode}}`)
} else {
addAttr(output.result, attrName, eval(`(function() {${attrCheckedCode}})`))
addHandler(output.result, 'change', eval(`(function(evt) {${eventChangeCode}})`))
}
return {
attr: { checked: attrCheckedCode },
events: { change: eventChangeCode }
Expand All @@ -125,8 +132,16 @@ function genRadioModel(node, attrName, value, output) {
const attrCheckedCode = `return ${exp(value, false)} === ${valueBinding}`
const eventChangeCode = `${exp(value, false)} = ${valueBinding}`

addAttr(output.result, attrName, eval(`(function() {${attrCheckedCode}})`))
addHandler(output.result, 'change', eval(`(function(evt) {${eventChangeCode}})`))
const isCard = output.isCard
const isLite = output.isLite
if (isCard && !isLite) {
addAttr(output.result, attrName, `(function() {${attrCheckedCode}})`)
addAttr(output.result, attrName + 'Raw', value)
addHandler(output.result, 'change', `function(evt) {${eventChangeCode}}`)
} else {
addAttr(output.result, attrName, eval(`(function() {${attrCheckedCode}})`))
addHandler(output.result, 'change', eval(`(function(evt) {${eventChangeCode}})`))
}

return {
attr: { checked: attrCheckedCode },
Expand All @@ -140,11 +155,17 @@ function genRadioModel(node, attrName, value, output) {
* @param {object} output 构建的输出结果
*/
function genSelectModel(value, output) {
addHandler(
output.result,
'change',
eval(`(function(evt) { ${exp(value, false)} = evt.newValue})`)
)
const isCard = output.isCard
const isLite = output.isLite
if (isCard && !isLite) {
addHandler(output.result, 'change', `function(evt) { ${exp(value, false)} = evt.newValue}`)
} else {
addHandler(
output.result,
'change',
eval(`(function(evt) { ${exp(value, false)} = evt.newValue})`)
)
}
}

/**
Expand All @@ -156,10 +177,16 @@ function genSelectModel(value, output) {
*/
function genDefaultModel(attrName, value, output) {
const eventChangeCode = `${exp(value, false)} = evt.target.value`

addAttr(output.result, attrName, exp(value))
addHandler(output.result, 'change', eval(`(function(evt) {${eventChangeCode}})`))

const isCard = output.isCard
const isLite = output.isLite
if (isCard && !isLite) {
addAttr(output.result, attrName, exp(value, true, isLite, isCard))
addAttr(output.result, attrName + 'Raw', value)
addHandler(output.result, 'change', `function(evt) {${eventChangeCode}}`)
} else {
addAttr(output.result, attrName, exp(value))
addHandler(output.result, 'change', eval(`(function(evt) {${eventChangeCode}})`))
}
return { events: { change: eventChangeCode } }
}

Expand All @@ -176,12 +203,22 @@ function genComponentModel(node, attrName, value, output, locationInfo, options)
// 自定义组件model指令绑定的属性,依然作为普通属性处理
validator.checkAttr(attrName, value, output, node.tagName, locationInfo, options)

// 为自定义组件绑定update:${attrName}事件,接收组件内部emit的update:${attrName}事件
addHandler(
output.result,
`update:${attrName}`,
eval(`(function(evt) { ${exp(value, false)} = evt.detail})`)
)
const isCard = output.isCard
const isLite = output.isLite
if (isCard && !isLite) {
addHandler(
output.result,
`update:${attrName}`,
`function(evt) { ${exp(value, false)} = evt.detail}`
)
} else {
// 为自定义组件绑定update:${attrName}事件,接收组件内部emit的update:${attrName}事件
addHandler(
output.result,
`update:${attrName}`,
eval(`(function(evt) { ${exp(value, false)} = evt.detail})`)
)
}
}

/**
Expand All @@ -196,40 +233,76 @@ function genDynamicModel(node, attrName, value, output, expType) {
const checkboxCode = genCheckboxModel(node, attrName, value, output)
const radioCode = genRadioModel(node, attrName, value, output)
const textCode = genDefaultModel(attrName, value, output)
const isCard = output.isCard
const isLite = output.isLite
if (isCard && !isLite) {
addAttr(output.result, attrName, exp(value, true, isLite, isCard))
addAttr(output.result, attrName + 'Raw', value)

addAttr(output.result, attrName, exp(value))
addAttr(
output.result,
'checked',
`(function() {
if (${expType} === 'checkbox') {
${checkboxCode.attr.checked}
} else if (${expType} === 'radio') {
${radioCode.attr.checked}
} else {
return false
}
})
`
)

addAttr(
output.result,
'checked',
eval(`
(function() {
if (${expType} === 'checkbox') {
${checkboxCode.attr.checked}
} else if (${expType} === 'radio') {
${radioCode.attr.checked}
} else {
return false
}
})
`)
)
addAttr(output.result, 'checkedRaw', value)
addHandler(
output.result,
'change',
`function(evt) {
if (${expType} === 'checkbox') {
${checkboxCode.events.change}
} else if (${expType} === 'radio') {
${radioCode.events.change}
} else {
${textCode.events.change}
}
}`
)
} else {
addAttr(output.result, attrName, exp(value))

addHandler(
output.result,
'change',
eval(`
(function(evt) {
if (${expType} === 'checkbox') {
${checkboxCode.events.change}
} else if (${expType} === 'radio') {
${radioCode.events.change}
} else {
${textCode.events.change}
}
})
`)
)
addAttr(
output.result,
'checked',
eval(`
(function() {
if (${expType} === 'checkbox') {
${checkboxCode.attr.checked}
} else if (${expType} === 'radio') {
${radioCode.attr.checked}
} else {
return false
}
})
`)
)

addHandler(
output.result,
'change',
eval(`
(function(evt) {
if (${expType} === 'checkbox') {
${checkboxCode.events.change}
} else if (${expType} === 'radio') {
${radioCode.events.change}
} else {
${textCode.events.change}
}
})
`)
)
}
}

/**
Expand Down
Loading
Loading