[improvement] use scoped-slots (#2712)

This commit is contained in:
neverland 2019-02-11 17:52:43 +08:00 committed by GitHub
parent 9f7c91a3b9
commit 9c4ad97731
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 159 additions and 122 deletions

View File

@ -19,41 +19,43 @@ export default sfc({
onSelect(express) {
this.$emit('select-search', express);
this.$emit('input', `${express.address || ''} ${express.name || ''}`.trim());
},
onFinish() {
this.$refs.field.blur();
},
renderFinish() {
const showFinish = this.value && this.focused && android;
if (showFinish) {
return (
<div class={bem('finish')} onClick={this.onFinish}>
{t('complete')}
</div>
);
}
},
renderSearchResult() {
const showSearchList = this.focused && this.searchResult && this.showSearchResult;
if (showSearchList) {
return this.searchResult.map(express => (
<Cell
key={express.name + express.address}
title={express.name}
label={express.address}
icon="location-o"
clickable
onClick={() => {
this.onSelect(express);
}}
/>
));
}
}
},
render(h) {
const { value, focused, searchResult } = this;
const Finish = value && focused && android && (
<div
slot="icon"
class={bem('finish')}
onClick={() => {
this.$refs.field.blur();
}}
>
{t('complete')}
</div>
);
const SearchList =
focused &&
searchResult &&
this.showSearchResult &&
searchResult.map(express => (
<Cell
key={express.name + express.address}
title={express.name}
label={express.address}
icon="location-o"
clickable
onClick={() => {
this.onSelect(express);
}}
/>
));
return (
<Cell class={bem()}>
<Field
@ -67,11 +69,10 @@ export default sfc({
error={this.error}
label={t('label')}
placeholder={t('placeholder')}
scopedSlots={{ icon: this.renderFinish }}
{...{ on: this.$listeners }}
>
{Finish}
</Field>
{SearchList}
/>
{this.renderSearchResult()}
</Cell>
);
}

View File

@ -17,33 +17,41 @@ export default sfc({
if (this.switchable) {
this.$emit('select');
}
},
onClickRightIcon(event) {
event.stopPropagation();
this.$emit('edit');
},
renderRightIcon() {
return <Icon name="edit" class={bem('edit')} onClick={this.onClickRightIcon} />;
},
renderContent() {
const { data } = this;
const Info = [
<div class={bem('name')}>{`${data.name}${data.tel}`}</div>,
<div class={bem('address')}>{data.address}</div>
];
return this.disabled ? Info : <Radio name={data.id}>{Info}</Radio>;
}
},
render(h) {
const { data, disabled, switchable } = this;
const Info = [
<div class={bem('name')}>{`${data.name}${data.tel}`}</div>,
<div class={bem('address')}>{data.address}</div>
];
const { disabled, switchable } = this;
return (
<Cell
class={bem({ disabled, unswitchable: !switchable })}
isLink={!disabled && switchable}
scopedSlots={{
default: this.renderContent,
'right-icon': this.renderRightIcon
}}
onClick={this.onSelect}
>
{disabled ? Info : <Radio name={data.id}>{Info}</Radio>}
<Icon
slot="right-icon"
name="edit"
class={bem('edit')}
onClick={event => {
event.stopPropagation();
this.$emit('edit');
}}
/>
</Cell>
/>
);
}
});

View File

@ -23,24 +23,28 @@ export default sfc({
<Cell
key={item.id}
isLink
scopedSlots={{
default: () => (
<Radio name={item.id}>
<div class={bem('name')}>{`${item.name}${item.tel}`}</div>
</Radio>
),
'right-icon': () => (
<Icon
name="edit"
class={bem('edit')}
onClick={event => {
event.stopPropagation();
listeners.edit && listeners.edit(item, index);
}}
/>
)
}}
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 (

View File

@ -123,6 +123,29 @@ export default sfc({
list.scrollTop = card[index].$el.offsetTop - 100;
}
});
},
renderEmpty() {
return (
<div class={bem('empty')}>
<img src={EMPTY_IMAGE} />
<p>{t('empty')}</p>
</div>
);
},
renderExchangeButton() {
return (
<Button
size="small"
type="danger"
class={bem('exchange')}
text={this.exchangeButtonText || t('exchange')}
loading={this.exchangeButtonLoading}
disabled={this.buttonDisabled}
onClick={this.onClickExchangeButton}
/>
);
}
},
@ -135,25 +158,10 @@ export default sfc({
class={bem('field')}
placeholder={this.inputPlaceholder || t('placeholder')}
maxlength="20"
>
<Button
slot="button"
size="small"
type="danger"
class={bem('exchange')}
text={this.exchangeButtonText || t('exchange')}
loading={this.exchangeButtonLoading}
disabled={this.buttonDisabled}
onClick={this.onClickExchangeButton}
/>
</Field>
);
const Empty = (
<div class={bem('empty')}>
<img src={EMPTY_IMAGE} />
<p>{t('empty')}</p>
</div>
scopedSlots={{
button: this.renderExchangeButton
}}
/>
);
const onChange = index => () => this.$emit('change', index);
@ -171,7 +179,7 @@ export default sfc({
nativeOnClick={onChange(index)}
/>
))}
{!this.coupons.length && Empty}
{!this.coupons.length && this.renderEmpty()}
</div>
</Tab>
);
@ -182,7 +190,7 @@ export default sfc({
{this.disabledCoupons.map(coupon => (
<Coupon disabled key={coupon.id} coupon={coupon} currency={this.currency} />
))}
{!this.disabledCoupons.length && Empty}
{!this.disabledCoupons.length && this.renderEmpty}
</div>
</Tab>
);

View File

@ -163,41 +163,55 @@ export default sfc({
if (height) {
input.style.height = height + 'px';
}
},
renderInput() {
const inputProps = {
ref: 'input',
class: bem('control', this.inputAlign),
domProps: {
value: this.value
},
attrs: {
...this.$attrs,
readonly: this.readonly
},
on: this.listeners
};
if (this.type === 'textarea') {
return <textarea {...inputProps} />;
}
return <input type={this.type} {...inputProps} />;
},
renderLeftIcon() {
const showLeftIcon = this.slots('left-icon') || this.leftIcon;
if (showLeftIcon) {
return (
<div class={bem('left-icon')} onClick={this.onClickLeftIcon}>
{this.slots('left-icon') || <Icon name={this.leftIcon} />}
</div>
);
}
},
renderRightIcon() {
const { slots } = this;
const showRightIcon = slots('right-icon') || slots('icon') || this.rightIcon || this.icon;
if (showRightIcon) {
return (
<div class={bem('right-icon')} onClick={this.onClickRightIcon}>
{slots('right-icon') || slots('icon') || <Icon name={this.rightIcon || this.icon} />}
</div>
);
}
}
},
render(h) {
const { type, labelAlign, slots } = this;
const showLeftIcon = slots('left-icon') || this.leftIcon;
const showRightIcon = slots('right-icon') || slots('icon') || this.rightIcon || this.icon;
const LeftIcon = showLeftIcon && (
<div slot="icon" class={bem('left-icon')} onClick={this.onClickLeftIcon}>
{slots('left-icon') || <Icon name={this.leftIcon} />}
</div>
);
const RightIcon = showRightIcon && (
<div class={bem('right-icon')} onClick={this.onClickRightIcon}>
{slots('right-icon') || slots('icon') || <Icon name={this.rightIcon || this.icon} />}
</div>
);
const inputProps = {
ref: 'input',
class: bem('control', this.inputAlign),
domProps: {
value: this.value
},
attrs: {
...this.$attrs,
readonly: this.readonly
},
on: this.listeners
};
const Input = type === 'textarea' ? <textarea {...inputProps} /> : <input type={type} {...inputProps} />;
const { slots, labelAlign } = this;
return (
<Cell
icon={this.leftIcon}
@ -210,15 +224,17 @@ export default sfc({
error: this.error,
disabled: this.$attrs.disabled,
[`label-${labelAlign}`]: labelAlign,
'min-height': type === 'textarea' && !this.autosize
'min-height': this.type === 'textarea' && !this.autosize
})}
scopedSlots={{
icon: this.renderLeftIcon
}}
>
{LeftIcon}
{h('template', { slot: 'title' }, slots('label'))}
<div class={bem('body')}>
{Input}
{this.renderInput()}
{this.showClear && <Icon name="clear" class={bem('clear')} onTouchstart={this.onClear} />}
{RightIcon}
{this.renderRightIcon()}
{slots('button') && <div class={bem('button')}>{slots('button')}</div>}
</div>
{this.errorMessage && <div class={bem('error-message')}>{this.errorMessage}</div>}