[improvement] declare functional sfc (#2695)

This commit is contained in:
neverland 2019-02-06 21:11:12 +08:00 committed by GitHub
parent 061382014d
commit 1b60e4df80
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 465 additions and 494 deletions

View File

@ -3,70 +3,69 @@ import Loading from '../loading';
const [sfc, bem] = use('button'); const [sfc, bem] = use('button');
export default sfc( export default sfc({
{ functional: true,
props: {
text: String, props: {
block: Boolean, text: String,
plain: Boolean, block: Boolean,
round: Boolean, plain: Boolean,
square: Boolean, round: Boolean,
loading: Boolean, square: Boolean,
disabled: Boolean, loading: Boolean,
nativeType: String, disabled: Boolean,
bottomAction: Boolean, nativeType: String,
tag: { bottomAction: Boolean,
type: String, tag: {
default: 'button' type: String,
}, default: 'button'
type: {
type: String,
default: 'default'
},
size: {
type: String,
default: 'normal'
}
}, },
type: {
render(h, context, inherit) { type: String,
const { props, listeners } = context; default: 'default'
const { type, disabled, loading } = props; },
size: {
const onClick = event => { type: String,
if (!loading && !disabled && listeners.click) { default: 'normal'
listeners.click(event);
}
};
return (
<props.tag
type={props.nativeType}
disabled={disabled}
class={bem([
type,
props.size,
{
loading,
disabled,
block: props.block,
plain: props.plain,
round: props.round,
square: props.square,
'bottom-action': props.bottomAction
}
])}
onClick={onClick}
{...inherit}
>
{loading ? (
<Loading size="20px" color={type === 'default' ? undefined : ''} />
) : (
<span class={bem('text')}>{context.children || props.text}</span>
)}
</props.tag>
);
} }
}, },
true
); render(h, context, inherit) {
const { props, listeners } = context;
const { type, disabled, loading } = props;
const onClick = event => {
if (!loading && !disabled && listeners.click) {
listeners.click(event);
}
};
return (
<props.tag
type={props.nativeType}
disabled={disabled}
class={bem([
type,
props.size,
{
loading,
disabled,
block: props.block,
plain: props.plain,
round: props.round,
square: props.square,
'bottom-action': props.bottomAction
}
])}
onClick={onClick}
{...inherit}
>
{loading ? (
<Loading size="20px" color={type === 'default' ? undefined : ''} />
) : (
<span class={bem('text')}>{context.children || props.text}</span>
)}
</props.tag>
);
}
});

View File

@ -2,25 +2,21 @@ import { use } from '../utils';
const [sfc, bem] = use('cell-group'); const [sfc, bem] = use('cell-group');
export default sfc( export default sfc({
{ functional: true,
props: {
border: {
type: Boolean,
default: true
}
},
render(h, context) { props: {
return ( border: {
<div type: Boolean,
class={[bem(), { 'van-hairline--top-bottom': context.props.border }]} default: true
{...context.data}
>
{context.children}
</div>
);
} }
}, },
true
); render(h, context) {
return (
<div class={[bem(), { 'van-hairline--top-bottom': context.props.border }]} {...context.data}>
{context.children}
</div>
);
}
});

View File

@ -7,57 +7,56 @@ import RadioGroup from '../radio-group';
const [sfc, bem, t] = use('contact-list'); const [sfc, bem, t] = use('contact-list');
export default sfc( export default sfc({
{ functional: true,
props: {
value: null,
list: Array,
addText: String
},
render(h, context, inherit) { props: {
const { props, listeners } = context; value: null,
list: Array,
const List = props.list.map((item, index) => ( addText: String
<Cell
key={item.id}
isLink
onClick={() => {
listeners.input && listeners.input(item.id);
listeners.select && listeners.select(item, index);
}}
>
<Radio name={item.id}>
<div class={bem('name')}>{`${item.name}${item.tel}`}</div>
</Radio>
<Icon
slot="right-icon"
name="edit"
class={bem('edit')}
onClick={event => {
event.stopPropagation();
listeners.edit && listeners.edit(item, index);
}}
/>
</Cell>
));
return (
<div class={bem()} {...inherit}>
<RadioGroup value={props.value} class={bem('group')}>
{List}
</RadioGroup>
<Button
square
size="large"
type="danger"
class={bem('add')}
text={props.addText || t('addText')}
onClick={listeners.add || noop}
/>
</div>
);
}
}, },
true
); render(h, context, inherit) {
const { props, listeners } = context;
const List = props.list.map((item, index) => (
<Cell
key={item.id}
isLink
onClick={() => {
listeners.input && listeners.input(item.id);
listeners.select && listeners.select(item, index);
}}
>
<Radio name={item.id}>
<div class={bem('name')}>{`${item.name}${item.tel}`}</div>
</Radio>
<Icon
slot="right-icon"
name="edit"
class={bem('edit')}
onClick={event => {
event.stopPropagation();
listeners.edit && listeners.edit(item, index);
}}
/>
</Cell>
));
return (
<div class={bem()} {...inherit}>
<RadioGroup value={props.value} class={bem('group')}>
{List}
</RadioGroup>
<Button
square
size="large"
type="danger"
class={bem('add')}
text={props.addText || t('addText')}
onClick={listeners.add || noop}
/>
</div>
);
}
});

View File

@ -2,15 +2,14 @@ import { use } from '../utils';
const [sfc, bem] = use('goods-action'); const [sfc, bem] = use('goods-action');
export default sfc( export default sfc({
{ functional: true,
render(h, context) {
return ( render(h, context) {
<div class={bem()} {...context.data}> return (
{context.children} <div class={bem()} {...context.data}>
</div> {context.children}
); </div>
} );
}, }
true });
);

View File

@ -4,41 +4,40 @@ import isSrc from '../utils/validate/src';
const [sfc] = use('icon'); const [sfc] = use('icon');
export default sfc( export default sfc({
{ functional: true,
props: {
name: String,
size: String,
color: String,
info: [String, Number],
classPrefix: {
type: String,
default: 'van-icon'
}
},
render(h, context) { props: {
const { props } = context; name: String,
const urlIcon = isSrc(props.name); size: String,
color: String,
return ( info: [String, Number],
<i classPrefix: {
class={[ type: String,
props.classPrefix, default: 'van-icon'
urlIcon ? 'van-icon--image' : `${props.classPrefix}-${props.name}`
]}
style={{
color: props.color,
fontSize: props.size
}}
{...context.data}
>
{context.children}
{urlIcon && <img src={props.name} />}
<Info info={props.info} />
</i>
);
} }
}, },
true
); render(h, context) {
const { props } = context;
const urlIcon = isSrc(props.name);
return (
<i
class={[
props.classPrefix,
urlIcon ? 'van-icon--image' : `${props.classPrefix}-${props.name}`
]}
style={{
color: props.color,
fontSize: props.size
}}
{...context.data}
>
{context.children}
{urlIcon && <img src={props.name} />}
<Info info={props.info} />
</i>
);
}
});

View File

@ -2,21 +2,20 @@ import { use, isDef } from '../utils';
const [sfc, bem] = use('info'); const [sfc, bem] = use('info');
export default sfc( export default sfc({
{ functional: true,
props: {
info: [String, Number]
},
render(h, { props, data }) { props: {
return ( info: [String, Number]
isDef(props.info) && (
<div class={bem()} {...data}>
{props.info}
</div>
)
);
}
}, },
true
); render(h, { props, data }) {
return (
isDef(props.info) && (
<div class={bem()} {...data}>
{props.info}
</div>
)
);
}
});

View File

@ -3,53 +3,52 @@ import { use } from '../utils';
const [sfc, bem] = use('loading'); const [sfc, bem] = use('loading');
const DEFAULT_COLOR = '#c9c9c9'; const DEFAULT_COLOR = '#c9c9c9';
export default sfc( export default sfc({
{ functional: true,
props: {
size: String, props: {
type: { size: String,
type: String, type: {
default: 'circular' type: String,
}, default: 'circular'
color: {
type: String,
default: DEFAULT_COLOR
}
}, },
color: {
render(h, context) { type: String,
const { color, size, type } = context.props; default: DEFAULT_COLOR
const colorType = color === 'white' || color === 'black' ? color : '';
const style = {
color: color === 'black' ? DEFAULT_COLOR : color,
width: size,
height: size
};
const Spin = [];
if (type === 'spinner') {
for (let i = 0; i < 12; i++) {
Spin.push(<i />);
}
}
const Circular = type === 'circular' && (
<svg class={bem('circular')} viewBox="25 25 50 50">
<circle cx="50" cy="50" r="20" fill="none" />
</svg>
);
return (
<div class={bem([type, colorType])} style={style} {...context.data}>
<span class={bem('spinner', type)}>
{Spin}
{Circular}
</span>
</div>
);
} }
}, },
true
); render(h, context) {
const { color, size, type } = context.props;
const colorType = color === 'white' || color === 'black' ? color : '';
const style = {
color: color === 'black' ? DEFAULT_COLOR : color,
width: size,
height: size
};
const Spin = [];
if (type === 'spinner') {
for (let i = 0; i < 12; i++) {
Spin.push(<i />);
}
}
const Circular = type === 'circular' && (
<svg class={bem('circular')} viewBox="25 25 50 50">
<circle cx="50" cy="50" r="20" fill="none" />
</svg>
);
return (
<div class={bem([type, colorType])} style={style} {...context.data}>
<span class={bem('spinner', type)}>
{Spin}
{Circular}
</span>
</div>
);
}
});

View File

@ -3,53 +3,46 @@ import Icon from '../icon';
const [sfc, bem] = use('nav-bar'); const [sfc, bem] = use('nav-bar');
export default sfc( export default sfc({
{ functional: true,
props: {
title: String, props: {
fixed: Boolean, title: String,
leftText: String, fixed: Boolean,
rightText: String, leftText: String,
leftArrow: Boolean, rightText: String,
border: { leftArrow: Boolean,
type: Boolean, border: {
default: true type: Boolean,
}, default: true
zIndex: {
type: Number,
default: 1
}
}, },
zIndex: {
render(h, context, inherit) { type: Number,
const { props, listeners } = context; default: 1
const slots = context.slots();
return (
<div
class={[bem({ fixed: props.fixed }), { 'van-hairline--bottom': props.border }]}
style={{ zIndex: props.zIndex }}
{...inherit}
>
<div
class={bem('left')}
onClick={listeners['click-left'] || noop}
>
{slots.left || [
props.leftArrow && <Icon class={bem('arrow')} name="arrow-left" />,
props.leftText && <span class={bem('text')}>{props.leftText}</span>
]}
</div>
<div class={[bem('title'), 'van-ellipsis']}>{slots.title || props.title}</div>
<div
class={bem('right')}
onClick={listeners['click-right'] || noop}
>
{slots.right || (props.rightText && <span class={bem('text')}>{props.rightText}</span>)}
</div>
</div>
);
} }
}, },
true
); render(h, context, inherit) {
const { props, listeners } = context;
const slots = context.slots();
return (
<div
class={[bem({ fixed: props.fixed }), { 'van-hairline--bottom': props.border }]}
style={{ zIndex: props.zIndex }}
{...inherit}
>
<div class={bem('left')} onClick={listeners['click-left'] || noop}>
{slots.left || [
props.leftArrow && <Icon class={bem('arrow')} name="arrow-left" />,
props.leftText && <span class={bem('text')}>{props.leftText}</span>
]}
</div>
<div class={[bem('title'), 'van-ellipsis']}>{slots.title || props.title}</div>
<div class={bem('right')} onClick={listeners['click-right'] || noop}>
{slots.right || (props.rightText && <span class={bem('text')}>{props.rightText}</span>)}
</div>
</div>
);
}
});

View File

@ -4,35 +4,34 @@ import CellGroup from '../cell-group';
const [sfc, bem] = use('panel'); const [sfc, bem] = use('panel');
export default sfc( export default sfc({
{ functional: true,
props: {
icon: String,
desc: String,
title: String,
status: String
},
render(h, context) { props: {
const { props } = context; icon: String,
const slots = context.slots(); desc: String,
title: String,
return ( status: String
<CellGroup class={bem()} {...context.data}>
{slots.header || (
<Cell
class={bem('header')}
icon={props.icon}
label={props.desc}
title={props.title}
value={props.status}
/>
)}
<div class={bem('content')}>{slots.default}</div>
{slots.footer && <div class={[bem('footer'), 'van-hairline--top']}>{slots.footer}</div>}
</CellGroup>
);
}
}, },
true
); render(h, context) {
const { props } = context;
const slots = context.slots();
return (
<CellGroup class={bem()} {...context.data}>
{slots.header || (
<Cell
class={bem('header')}
icon={props.icon}
label={props.desc}
title={props.title}
value={props.status}
/>
)}
<div class={bem('content')}>{slots.default}</div>
{slots.footer && <div class={[bem('footer'), 'van-hairline--top']}>{slots.footer}</div>}
</CellGroup>
);
}
});

View File

@ -2,50 +2,49 @@ import { use } from '../utils';
const [sfc, bem] = use('password-input'); const [sfc, bem] = use('password-input');
export default sfc( export default sfc({
{ functional: true,
props: {
info: String, props: {
errorInfo: String, info: String,
value: { errorInfo: String,
type: String, value: {
default: '' type: String,
}, default: ''
length: {
type: Number,
default: 6
}
}, },
length: {
render(h, context) { type: Number,
const { props, listeners } = context; default: 6
const info = props.errorInfo || props.info;
const Points = [];
for (let i = 0; i < props.length; i++) {
Points.push(
<li class="van-hairline">
<i style={{ visibility: props.value[i] ? 'visible' : 'hidden' }} />
</li>
);
}
return (
<div class={bem()}>
<ul
class={[bem('security'), 'van-hairline--surround']}
onTouchstart={event => {
event.stopPropagation();
listeners.focus && listeners.focus();
}}
{...context.data}
>
{Points}
</ul>
{info && <div class={bem(props.errorInfo ? 'error-info' : 'info')}>{info}</div>}
</div>
);
} }
}, },
true
); render(h, context) {
const { props, listeners } = context;
const info = props.errorInfo || props.info;
const Points = [];
for (let i = 0; i < props.length; i++) {
Points.push(
<li class="van-hairline">
<i style={{ visibility: props.value[i] ? 'visible' : 'hidden' }} />
</li>
);
}
return (
<div class={bem()}>
<ul
class={[bem('security'), 'van-hairline--surround']}
onTouchstart={event => {
event.stopPropagation();
listeners.focus && listeners.focus();
}}
{...context.data}
>
{Points}
</ul>
{info && <div class={bem(props.errorInfo ? 'error-info' : 'info')}>{info}</div>}
</div>
);
}
});

View File

@ -3,64 +3,63 @@ import Button from '../button';
const [sfc, bem, t] = use('submit-bar'); const [sfc, bem, t] = use('submit-bar');
export default sfc( export default sfc({
{ functional: true,
props: {
tip: String, props: {
label: String, tip: String,
loading: Boolean, label: String,
disabled: Boolean, loading: Boolean,
buttonText: String, disabled: Boolean,
price: { buttonText: String,
type: Number, price: {
default: null type: Number,
}, default: null
currency: {
type: String,
default: '¥'
},
buttonType: {
type: String,
default: 'danger'
}
}, },
currency: {
render(h, context, inherit) { type: String,
const { props, listeners } = context; default: '¥'
const { tip, price } = props; },
const slots = context.slots(); buttonType: {
const hasPrice = typeof price === 'number'; type: String,
default: 'danger'
return (
<div class={bem()} {...inherit}>
{slots.top}
{(slots.tip || tip) && (
<div class={bem('tip')}>
{tip}
{slots.tip}
</div>
)}
<div class={bem('bar')}>
{slots.default}
<div class={bem('text')}>
{hasPrice && [
<span>{props.label || t('label')}</span>,
<span class={bem('price')}>{`${props.currency} ${(price / 100).toFixed(2)}`}</span>
]}
</div>
<Button
square
size="large"
type={props.buttonType}
loading={props.loading}
disabled={props.disabled}
text={props.loading ? '' : props.buttonText}
onClick={listeners.submit || noop}
/>
</div>
</div>
);
} }
}, },
true
); render(h, context, inherit) {
const { props, listeners } = context;
const { tip, price } = props;
const slots = context.slots();
const hasPrice = typeof price === 'number';
return (
<div class={bem()} {...inherit}>
{slots.top}
{(slots.tip || tip) && (
<div class={bem('tip')}>
{tip}
{slots.tip}
</div>
)}
<div class={bem('bar')}>
{slots.default}
<div class={bem('text')}>
{hasPrice && [
<span>{props.label || t('label')}</span>,
<span class={bem('price')}>{`${props.currency} ${(price / 100).toFixed(2)}`}</span>
]}
</div>
<Button
square
size="large"
type={props.buttonType}
loading={props.loading}
disabled={props.disabled}
text={props.loading ? '' : props.buttonText}
onClick={listeners.submit || noop}
/>
</div>
</div>
);
}
});

View File

@ -5,34 +5,27 @@ import SwitchMixin from '../mixins/switch';
const [sfc, bem] = use('switch-cell'); const [sfc, bem] = use('switch-cell');
export default sfc( export default sfc({
{ functional: true,
mixins: [SwitchMixin],
props: { mixins: [SwitchMixin],
title: String,
border: Boolean,
size: {
type: String,
default: '24px'
}
},
render(h, context, inherit) { props: {
const { props } = context; title: String,
border: Boolean,
return ( size: {
<Cell type: String,
center default: '24px'
title={props.title}
border={props.border}
class={bem()}
{...inherit}
>
<Switch {...{ props, on: context.listeners }} />
</Cell>
);
} }
}, },
true
); render(h, context, inherit) {
const { props } = context;
return (
<Cell center title={props.title} border={props.border} class={bem()} {...inherit}>
<Switch {...{ props, on: context.listeners }} />
</Cell>
);
}
});

View File

@ -9,45 +9,44 @@ const COLOR_MAP = {
success: GREEN success: GREEN
}; };
export default sfc( export default sfc({
{ functional: true,
props: {
size: String,
type: String,
mark: Boolean,
color: String,
plain: Boolean,
round: Boolean,
textColor: String
},
render(h, context) { props: {
const { props } = context; size: String,
const { mark, plain, round, size } = context.props; type: String,
mark: Boolean,
const color = props.color || COLOR_MAP[props.type] || GRAY_DARK; color: String,
const key = plain ? 'color' : 'backgroundColor'; plain: Boolean,
const style = { [key]: color }; round: Boolean,
textColor: String
if (props.textColor) {
style.color = props.textColor;
}
return (
<span
style={style}
class={[
bem({ mark, plain, round, [size]: size }),
{
'van-hairline--surround': plain
}
]}
{...context.data}
>
{context.children}
</span>
);
}
}, },
true
); render(h, context) {
const { props } = context;
const { mark, plain, round, size } = context.props;
const color = props.color || COLOR_MAP[props.type] || GRAY_DARK;
const key = plain ? 'color' : 'backgroundColor';
const style = { [key]: color };
if (props.textColor) {
style.color = props.textColor;
}
return (
<span
style={style}
class={[
bem({ mark, plain, round, [size]: size }),
{
'van-hairline--surround': plain
}
]}
{...context.data}
>
{context.children}
</span>
);
}
});

View File

@ -36,7 +36,6 @@ const mapInheritKey = { nativeOn: 'on' };
function functional(sfc) { function functional(sfc) {
const { render } = sfc; const { render } = sfc;
sfc.functional = true;
sfc.render = (h, context) => { sfc.render = (h, context) => {
const inherit = inheritKey.reduce((obj, key) => { const inherit = inheritKey.reduce((obj, key) => {
if (context.data[key]) { if (context.data[key]) {
@ -48,7 +47,7 @@ function functional(sfc) {
}; };
} }
export default name => (sfc, isFunctional) => { export default name => sfc => {
sfc.name = name; sfc.name = name;
sfc.install = install; sfc.install = install;
sfc.mixins = sfc.mixins || []; sfc.mixins = sfc.mixins || [];
@ -58,7 +57,7 @@ export default name => (sfc, isFunctional) => {
defaultProps(sfc.props); defaultProps(sfc.props);
} }
if (isFunctional) { if (sfc.functional) {
functional(sfc); functional(sfc);
} }