Skip to content

Commit f14c275

Browse files
committed
feat: add support for model and dir for new jscard package
Signed-off-by: lileirjyb <[email protected]>
1 parent 43b2a6a commit f14c275

File tree

9 files changed

+204
-94
lines changed

9 files changed

+204
-94
lines changed

packages/hap-compiler/src/template/index.js

-6
Original file line numberDiff line numberDiff line change
@@ -128,15 +128,9 @@ function traverse(node, output, previousNode, conditionList, options) {
128128
if (name.match(/^model:/)) {
129129
// 解析model指令,model指令格式:model:name="{{youName}}"
130130
validator.checkModel(name, value, output, node, locationInfo, options)
131-
if (output.isCard) {
132-
throw new Error('卡片不支持 model 指令')
133-
}
134131
} else if (name.match(/^dir:/)) {
135132
// 解析自定义指令,自定义指令格式:dir:指令名称="{{data}}"
136133
validator.checkCustomDirective(name, value, output, node)
137-
if (output.isCard) {
138-
throw new Error('卡片不支持自定义指令')
139-
}
140134
} else {
141135
// 其余为普通属性
142136
validator.checkAttr(name, value, output, node.tagName, locationInfo, options)

packages/hap-compiler/src/template/model.js

+124-51
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,16 @@ function genCheckboxModel(node, attrName, value, output) {
102102
${expValue} = checked ? ${trueValueBinding} : ${falseValueBinding}
103103
}`
104104

105-
addAttr(output.result, attrName, eval(`(function() {${attrCheckedCode}})`))
106-
addHandler(output.result, 'change', eval(`(function(evt) {${eventChangeCode}})`))
107-
105+
const isCard = output.isCard
106+
const isLite = output.isLite
107+
if (isCard && !isLite) {
108+
addAttr(output.result, attrName, `(function() {${attrCheckedCode}})`)
109+
addAttr(output.result, attrName + 'Raw', value)
110+
addHandler(output.result, 'change', `function(evt) {${eventChangeCode}}`)
111+
} else {
112+
addAttr(output.result, attrName, eval(`(function() {${attrCheckedCode}})`))
113+
addHandler(output.result, 'change', eval(`(function(evt) {${eventChangeCode}})`))
114+
}
108115
return {
109116
attr: { checked: attrCheckedCode },
110117
events: { change: eventChangeCode }
@@ -125,8 +132,16 @@ function genRadioModel(node, attrName, value, output) {
125132
const attrCheckedCode = `return ${exp(value, false)} === ${valueBinding}`
126133
const eventChangeCode = `${exp(value, false)} = ${valueBinding}`
127134

128-
addAttr(output.result, attrName, eval(`(function() {${attrCheckedCode}})`))
129-
addHandler(output.result, 'change', eval(`(function(evt) {${eventChangeCode}})`))
135+
const isCard = output.isCard
136+
const isLite = output.isLite
137+
if (isCard && !isLite) {
138+
addAttr(output.result, attrName, `(function() {${attrCheckedCode}})`)
139+
addAttr(output.result, attrName + 'Raw', value)
140+
addHandler(output.result, 'change', `function(evt) {${eventChangeCode}}`)
141+
} else {
142+
addAttr(output.result, attrName, eval(`(function() {${attrCheckedCode}})`))
143+
addHandler(output.result, 'change', eval(`(function(evt) {${eventChangeCode}})`))
144+
}
130145

131146
return {
132147
attr: { checked: attrCheckedCode },
@@ -140,11 +155,17 @@ function genRadioModel(node, attrName, value, output) {
140155
* @param {object} output 构建的输出结果
141156
*/
142157
function genSelectModel(value, output) {
143-
addHandler(
144-
output.result,
145-
'change',
146-
eval(`(function(evt) { ${exp(value, false)} = evt.newValue})`)
147-
)
158+
const isCard = output.isCard
159+
const isLite = output.isLite
160+
if (isCard && !isLite) {
161+
addHandler(output.result, 'change', `function(evt) { ${exp(value, false)} = evt.newValue}`)
162+
} else {
163+
addHandler(
164+
output.result,
165+
'change',
166+
eval(`(function(evt) { ${exp(value, false)} = evt.newValue})`)
167+
)
168+
}
148169
}
149170

150171
/**
@@ -156,10 +177,16 @@ function genSelectModel(value, output) {
156177
*/
157178
function genDefaultModel(attrName, value, output) {
158179
const eventChangeCode = `${exp(value, false)} = evt.target.value`
159-
160-
addAttr(output.result, attrName, exp(value))
161-
addHandler(output.result, 'change', eval(`(function(evt) {${eventChangeCode}})`))
162-
180+
const isCard = output.isCard
181+
const isLite = output.isLite
182+
if (isCard && !isLite) {
183+
addAttr(output.result, attrName, exp(value, true, isLite, isCard))
184+
addAttr(output.result, attrName + 'Raw', value)
185+
addHandler(output.result, 'change', `function(evt) {${eventChangeCode}}`)
186+
} else {
187+
addAttr(output.result, attrName, exp(value))
188+
addHandler(output.result, 'change', eval(`(function(evt) {${eventChangeCode}})`))
189+
}
163190
return { events: { change: eventChangeCode } }
164191
}
165192

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

179-
// 为自定义组件绑定update:${attrName}事件,接收组件内部emit的update:${attrName}事件
180-
addHandler(
181-
output.result,
182-
`update:${attrName}`,
183-
eval(`(function(evt) { ${exp(value, false)} = evt.detail})`)
184-
)
206+
const isCard = output.isCard
207+
const isLite = output.isLite
208+
if (isCard && !isLite) {
209+
addHandler(
210+
output.result,
211+
`update:${attrName}`,
212+
`function(evt) { ${exp(value, false)} = evt.detail}`
213+
)
214+
} else {
215+
// 为自定义组件绑定update:${attrName}事件,接收组件内部emit的update:${attrName}事件
216+
addHandler(
217+
output.result,
218+
`update:${attrName}`,
219+
eval(`(function(evt) { ${exp(value, false)} = evt.detail})`)
220+
)
221+
}
185222
}
186223

187224
/**
@@ -196,40 +233,76 @@ function genDynamicModel(node, attrName, value, output, expType) {
196233
const checkboxCode = genCheckboxModel(node, attrName, value, output)
197234
const radioCode = genRadioModel(node, attrName, value, output)
198235
const textCode = genDefaultModel(attrName, value, output)
236+
const isCard = output.isCard
237+
const isLite = output.isLite
238+
if (isCard && !isLite) {
239+
addAttr(output.result, attrName, exp(value, true, isLite, isCard))
240+
addAttr(output.result, attrName + 'Raw', value)
199241

200-
addAttr(output.result, attrName, exp(value))
242+
addAttr(
243+
output.result,
244+
'checked',
245+
`(function() {
246+
if (${expType} === 'checkbox') {
247+
${checkboxCode.attr.checked}
248+
} else if (${expType} === 'radio') {
249+
${radioCode.attr.checked}
250+
} else {
251+
return false
252+
}
253+
})
254+
`
255+
)
201256

202-
addAttr(
203-
output.result,
204-
'checked',
205-
eval(`
206-
(function() {
207-
if (${expType} === 'checkbox') {
208-
${checkboxCode.attr.checked}
209-
} else if (${expType} === 'radio') {
210-
${radioCode.attr.checked}
211-
} else {
212-
return false
213-
}
214-
})
215-
`)
216-
)
257+
addAttr(output.result, 'checkedRaw', value)
258+
addHandler(
259+
output.result,
260+
'change',
261+
`function(evt) {
262+
if (${expType} === 'checkbox') {
263+
${checkboxCode.events.change}
264+
} else if (${expType} === 'radio') {
265+
${radioCode.events.change}
266+
} else {
267+
${textCode.events.change}
268+
}
269+
}`
270+
)
271+
} else {
272+
addAttr(output.result, attrName, exp(value))
217273

218-
addHandler(
219-
output.result,
220-
'change',
221-
eval(`
222-
(function(evt) {
223-
if (${expType} === 'checkbox') {
224-
${checkboxCode.events.change}
225-
} else if (${expType} === 'radio') {
226-
${radioCode.events.change}
227-
} else {
228-
${textCode.events.change}
229-
}
230-
})
231-
`)
232-
)
274+
addAttr(
275+
output.result,
276+
'checked',
277+
eval(`
278+
(function() {
279+
if (${expType} === 'checkbox') {
280+
${checkboxCode.attr.checked}
281+
} else if (${expType} === 'radio') {
282+
${radioCode.attr.checked}
283+
} else {
284+
return false
285+
}
286+
})
287+
`)
288+
)
289+
290+
addHandler(
291+
output.result,
292+
'change',
293+
eval(`
294+
(function(evt) {
295+
if (${expType} === 'checkbox') {
296+
${checkboxCode.events.change}
297+
} else if (${expType} === 'radio') {
298+
${radioCode.events.change}
299+
} else {
300+
${textCode.events.change}
301+
}
302+
})
303+
`)
304+
)
305+
}
233306
}
234307

235308
/**

packages/hap-compiler/src/template/validator.js

+19-8
Original file line numberDiff line numberDiff line change
@@ -1423,7 +1423,6 @@ function checkId(id, output) {
14231423
const isLite = output.isLite
14241424
const isCard = output.isCard
14251425
output.result.id = exp.isExpr(id) ? exp(id, true, isLite, isCard) : id
1426-
output.result.idExpr = true
14271426
if (isCard && !isLite) {
14281427
output.result.idRaw = id
14291428
}
@@ -1824,9 +1823,9 @@ function checkEvent(name, value, output) {
18241823
value = '{{' + funcName + '(' + params.join(',') + ')}}'
18251824
try {
18261825
// 将事件转换为函数对象
1827-
if (output.isCard) {
1826+
if (output.isCard && !output.isLite) {
18281827
value = 'function (evt) { return ' + exp(value, false).replace('this.evt', 'evt') + '}'
1829-
} else if (!output.isLite) {
1828+
} else {
18301829
/* eslint-disable no-eval */
18311830
value = eval(
18321831
'(function (evt) { return ' + exp(value, false).replace('this.evt', 'evt') + '})'
@@ -1858,12 +1857,24 @@ function checkCustomDirective(name, value, output, node) {
18581857
colorconsole.warn(`\`${node.tagName}\` 组件自定义指令名称不能为空`)
18591858
return false
18601859
}
1861-
1860+
const isCard = output.isCard
1861+
const isLite = output.isLite
18621862
output.result.directives = output.result.directives || []
1863-
output.result.directives.push({
1864-
name: dirName,
1865-
value: exp.isExpr(value) ? exp(value, true, output.isLite, output.isCard) : value
1866-
})
1863+
if (isCard && !isLite) {
1864+
// 补全绑定值的双花括号,如:dir:指令名称="data"补全为dir:指令名称="{{data}}"
1865+
value = exp.addExprffix(value)
1866+
1867+
output.result.directives.push({
1868+
name: dirName,
1869+
value: exp.isExpr(value) ? exp(value, true, output.isLite, output.isCard) : value,
1870+
valueRaw: value
1871+
})
1872+
} else {
1873+
output.result.directives.push({
1874+
name: dirName,
1875+
value: exp.isExpr(value) ? exp(value, true, output.isLite, output.isCard) : value
1876+
})
1877+
}
18671878
}
18681879

18691880
/**

packages/hap-dsl-xvm/test/unit/ux/__snapshots__/component.test.js.snap

+14-14
Original file line numberDiff line numberDiff line change
@@ -4951,24 +4951,24 @@ exports[`Component 编译测试 ux components: ../../../lib/loaders/template-loa
49514951
\\"type\\": function () {return this.dynamicType},
49524952
\\"value\\": \\"test dynamic type\\",
49534953
\\"checked\\": function() {
4954-
if (this.dynamicType === 'checkbox') {
4955-
4954+
if (this.dynamicType === 'checkbox') {
4955+
49564956
if (Array.isArray(this.dynamicValue)) {
49574957
return this.dynamicValue.indexOf(\\"test dynamic type\\") > -1
49584958
} else {
49594959
return this.dynamicValue
49604960
}
4961-
} else if (this.dynamicType === 'radio') {
4962-
return this.dynamicValue === \\"test dynamic type\\"
4963-
} else {
4964-
return false
4961+
} else if (this.dynamicType === 'radio') {
4962+
return this.dynamicValue === \\"test dynamic type\\"
4963+
} else {
4964+
return false
4965+
}
49654966
}
4966-
}
49674967
},
49684968
\\"events\\": {
49694969
\\"change\\": function(evt) {
4970-
if (this.dynamicType === 'checkbox') {
4971-
4970+
if (this.dynamicType === 'checkbox') {
4971+
49724972
const checked = evt.target.checked;
49734973
if (Array.isArray(this.dynamicValue)) {
49744974
const index = this.dynamicValue.indexOf(\\"test dynamic type\\")
@@ -4980,12 +4980,12 @@ exports[`Component 编译测试 ux components: ../../../lib/loaders/template-loa
49804980
} else {
49814981
this.dynamicValue = checked ? true : false
49824982
}
4983-
} else if (this.dynamicType === 'radio') {
4984-
this.dynamicValue = \\"test dynamic type\\"
4985-
} else {
4986-
this.dynamicValue = evt.target.value
4983+
} else if (this.dynamicType === 'radio') {
4984+
this.dynamicValue = \\"test dynamic type\\"
4985+
} else {
4986+
this.dynamicValue = evt.target.value
4987+
}
49874988
}
4988-
}
49894989
}
49904990
},
49914991
{

packages/hap-packager/src/post-handler/js-card-post.js

+19-5
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,13 @@ function markClass(template) {
205205

206206
function markEvents(template) {
207207
if (template.events) {
208+
Object.keys(template.events).forEach((eventName) => {
209+
const eventStr = template.events[eventName]
210+
if (isFunctionStr(eventStr)) {
211+
template.events['$' + eventName] = eventStr
212+
delete template.events[eventName]
213+
}
214+
})
208215
template.kind = markKind(template.kind, ENUM_KIND_TYPE.ELEMENT.kind)
209216
}
210217
}
@@ -216,12 +223,14 @@ function markAttr(template) {
216223
if (isObject(attr)) {
217224
Object.keys(attr).forEach((attrKey) => {
218225
const attrValueRaw = attr[attrKey + 'Raw']
219-
if (isExpr(attrValueRaw)) {
220-
attr['$' + attrKey] = getExprRes(attrValueRaw, attr[attrKey])
221-
delete attr[attrKey]
222-
template.kind = markKind(template.kind, ENUM_KIND_TYPE.ELEMENT.kind)
226+
if (attrValueRaw !== undefined) {
227+
if (isExpr(attrValueRaw)) {
228+
attr['$' + attrKey] = getExprRes(attrValueRaw, attr[attrKey])
229+
delete attr[attrKey]
230+
template.kind = markKind(template.kind, ENUM_KIND_TYPE.ELEMENT.kind)
231+
}
232+
delete attr[attrKey + 'Raw']
223233
}
224-
delete attr[attrKey + 'Raw']
225234
})
226235
}
227236
}
@@ -231,6 +240,11 @@ function isExpr(val) {
231240
return validator.isExpr(val)
232241
}
233242

243+
function isFunctionStr(str) {
244+
const pattern = /^\s*function\s*\([\w\s,$]*\)\s*\{[\s\S]*\}\s*$/
245+
return pattern.test(str.trim())
246+
}
247+
234248
function isObject(obj) {
235249
return obj && Object.prototype.toString.call(obj) === '[object Object]' && obj !== null
236250
}

0 commit comments

Comments
 (0)