feat: classname 配置中类名支持表达式 Close: #8388 (#8392)

This commit is contained in:
liaoxuezhi 2023-10-17 13:56:15 +08:00 committed by GitHub
parent 6f599d5d93
commit 7f851fea0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 39 additions and 25 deletions

View File

@ -12,7 +12,9 @@ amis 中大部分的组件都支持配置 className 和 xxxClassName他可以
配置方式有两种:
1. 直接配置字符串如:`className: "text-danger"` 文字标红。
2. 采用对象配置,这个用法主要是方便写表达式如:`className: {"text-danger": "this.status == 1"}` 表示当数据 status 状态是 1 时,文字飘红。
2. 采用对象配置,这个用法主要是方便写表达式如:`className: {"text-danger": "${status == 1}"}` 表示当数据 status 状态是 1 时,文字飘红。
> 注意 3.5 版本开始类名中支持表达式如: `text-${status == 1 ? 'danger' : 'success'}`
```schema
{
@ -46,8 +48,9 @@ amis 中大部分的组件都支持配置 className 和 xxxClassName他可以
"2": "在线"
},
"className": {
"text-muted": "this.status == '1'",
"text-success": "this.status == '2'"
"text-muted": "${status == 1}",
"text-success": "${status == 2}",
"text-${status}": true
}
}
]

View File

@ -3,6 +3,7 @@ import {PlainObject} from '../types';
import {injectPropsToObject, mapObject} from './helper';
import isPlainObject from 'lodash/isPlainObject';
import cx from 'classnames';
import {tokenize} from './tokenize';
/**
* Props On
@ -29,17 +30,18 @@ export function getExprProperties(
}
let parts = /^(.*)(On|Expr|(?:c|C)lassName)(Raw)?$/.exec(key);
const type = parts?.[2];
let value: any = schema[key];
if (
value &&
typeof value === 'string' &&
parts?.[1] &&
(parts[2] === 'On' || parts[2] === 'Expr')
(type === 'On' || type === 'Expr')
) {
key = parts[1];
if (parts[2] === 'On' || parts[2] === 'Expr') {
if (type === 'On' || type === 'Expr') {
if (
!ctx &&
props &&
@ -51,7 +53,7 @@ export function getExprProperties(
});
}
if (parts[2] === 'On') {
if (type === 'On') {
value = props?.[key] || evalExpression(value, ctx || data);
} else {
value = filter(value, ctx || data);
@ -60,17 +62,22 @@ export function getExprProperties(
exprProps[key] = value;
} else if (
(type === 'className' || type === 'ClassName') &&
!props?.[key] && // 如果 props 里面有则是 props 优先
value &&
isPlainObject(value) &&
(parts?.[2] === 'className' || parts?.[2] === 'ClassName')
(typeof value === 'string' || isPlainObject(value))
) {
key = parts[1] + parts[2];
exprProps[`${key}Raw`] = value;
exprProps[key] = cx(
mapObject(value, (value: any) =>
typeof value === 'string' ? evalExpression(value, data) : value
)
);
exprProps[key] =
typeof value === 'string'
? tokenize(value, data)
: mapObject(
value,
(value: any) =>
typeof value === 'string' ? evalExpression(value, data) : value,
undefined,
(key: string) => tokenize(key, data)
);
}
});

View File

@ -1566,8 +1566,9 @@ export function chainEvents(props: any, schema: any) {
export function mapObject(
value: any,
fn: Function,
skipFn?: (value: any) => boolean
valueMapper: (value: any) => any,
skipFn?: (value: any) => boolean,
keyMapper?: (key: string) => string
): any {
// 如果value值满足skipFn条件则不做map操作
skipFn =
@ -1582,26 +1583,29 @@ export function mapObject(
return false;
};
if (!!skipFn(value)) {
if (skipFn(value)) {
return value;
}
if (Array.isArray(value)) {
return value.map(item => mapObject(item, fn, skipFn));
return value.map(item => mapObject(item, valueMapper, skipFn, keyMapper));
}
if (isObject(value)) {
let tmpValue = {...value};
Object.keys(tmpValue).forEach(key => {
(tmpValue as PlainObject)[key] = mapObject(
(tmpValue as PlainObject)[key],
fn,
skipFn
let tmpValue = {};
Object.keys(value).forEach(key => {
const newKey = keyMapper ? keyMapper(key) : key;
(tmpValue as PlainObject)[newKey] = mapObject(
(value as PlainObject)[key],
valueMapper,
skipFn,
keyMapper
);
});
return tmpValue;
}
return fn(value);
return valueMapper(value);
}
export function loadScript(src: string) {