[improvement] Use scoped-slots in Vue 2.6+ (#2688)

This commit is contained in:
neverland 2019-02-05 22:16:55 +08:00 committed by GitHub
parent 1ea92c023c
commit f768e75bfe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 125 additions and 117 deletions

View File

@ -113,12 +113,12 @@
"stylelint-config-standard": "^18.2.0", "stylelint-config-standard": "^18.2.0",
"uppercamelcase": "^3.0.0", "uppercamelcase": "^3.0.0",
"url-loader": "^1.1.2", "url-loader": "^1.1.2",
"vue": "2.6.1", "vue": "2.6.2",
"vue-jest": "4.0.0-beta.1", "vue-jest": "4.0.0-beta.1",
"vue-loader": "^15.6.2", "vue-loader": "^15.6.2",
"vue-router": "^3.0.2", "vue-router": "^3.0.2",
"vue-server-renderer": "^2.6.1", "vue-server-renderer": "^2.6.2",
"vue-template-compiler": "2.6.1", "vue-template-compiler": "2.6.2",
"vue-template-es2015-compiler": "^1.8.2", "vue-template-es2015-compiler": "^1.8.2",
"webpack": "^4.29.1", "webpack": "^4.29.1",
"webpack-cli": "^3.1.2", "webpack-cli": "^3.1.2",

View File

@ -83,7 +83,7 @@ export default sfc({
{cancelText} {cancelText}
</div> </div>
) : ( ) : (
<div class={bem('content')}>{this.$slots.default}</div> <div class={bem('content')}>{this.slots()}</div>
); );
return ( return (

View File

@ -279,7 +279,7 @@ export default sfc({
onFocus={onFocus('postalCode')} onFocus={onFocus('postalCode')}
/> />
)} )}
{this.$slots.default} {this.slots()}
{this.showSetDefault && ( {this.showSetDefault && (
<SwitchCell <SwitchCell
vModel={data.isDefault} vModel={data.isDefault}

View File

@ -40,13 +40,13 @@ export default sfc({
return ( return (
<div class={bem()}> <div class={bem()}>
{this.$slots.top} {this.slots('top')}
<RadioGroup value={this.value} onInput={event => this.$emit('input', event)}> <RadioGroup value={this.value} onInput={event => this.$emit('input', event)}>
{List} {List}
</RadioGroup> </RadioGroup>
{this.disabledText && <div class={bem('disabled-text')}>{this.disabledText}</div>} {this.disabledText && <div class={bem('disabled-text')}>{this.disabledText}</div>}
{DisabledList} {DisabledList}
{this.$slots.default} {this.slots()}
<Button <Button
square square
size="large" size="large"

View File

@ -23,6 +23,6 @@ export default sfc({
}, },
render(h) { render(h) {
return <div class={[bem(), 'van-hairline--top-bottom']}>{this.$slots.default}</div>; return <div class={[bem(), 'van-hairline--top-bottom']}>{this.slots()}</div>;
} }
}); });

View File

@ -22,17 +22,17 @@ export default sfc({
}, },
render(h) { render(h) {
const { thumb, $slots: slots } = this; const { thumb, slots } = this;
const showThumb = slots.thumb || thumb; const showThumb = slots('thumb') || thumb;
const showTag = slots.tag || this.tag; const showTag = slots('tag') || this.tag;
const showNum = slots.num || isDef(this.num); const showNum = slots('num') || isDef(this.num);
const showPrice = slots.price || isDef(this.price); const showPrice = slots('price') || isDef(this.price);
const showOriginPrice = slots['origin-price'] || isDef(this.originPrice); const showOriginPrice = slots('origin-price') || isDef(this.originPrice);
const Thumb = showThumb && ( const Thumb = showThumb && (
<a href={this.thumbLink} class={bem('thumb')}> <a href={this.thumbLink} class={bem('thumb')}>
{slots.thumb || {slots('thumb') ||
(this.lazyLoad ? ( (this.lazyLoad ? (
<img class={bem('img')} vLazy={thumb} /> <img class={bem('img')} vLazy={thumb} />
) : ( ) : (
@ -40,7 +40,7 @@ export default sfc({
))} ))}
{showTag && ( {showTag && (
<div class={bem('tag')}> <div class={bem('tag')}>
{slots.tag || ( {slots('tag') || (
<Tag mark type="danger"> <Tag mark type="danger">
{this.tag} {this.tag}
</Tag> </Tag>
@ -50,24 +50,24 @@ export default sfc({
</a> </a>
); );
const Title = slots.title || (this.title && <div class={bem('title')}>{this.title}</div>); const Title = slots('title') || (this.title && <div class={bem('title')}>{this.title}</div>);
const Desc = const Desc =
slots.desc || (this.desc && <div class={[bem('desc'), 'van-ellipsis']}>{this.desc}</div>); slots('desc') || (this.desc && <div class={[bem('desc'), 'van-ellipsis']}>{this.desc}</div>);
const Price = showPrice && ( const Price = showPrice && (
<div class={bem('price')}>{slots.price || `${this.currency} ${this.price}`}</div> <div class={bem('price')}>{slots('price') || `${this.currency} ${this.price}`}</div>
); );
const OriginPrice = showOriginPrice && ( const OriginPrice = showOriginPrice && (
<div class={bem('origin-price')}> <div class={bem('origin-price')}>
{slots['origin-price'] || `${this.currency} ${this.originPrice}`} {slots('origin-price') || `${this.currency} ${this.originPrice}`}
</div> </div>
); );
const Num = showNum && <div class={bem('num')}>{slots.num || `x ${this.num}`}</div>; const Num = showNum && <div class={bem('num')}>{slots('num') || `x ${this.num}`}</div>;
const Footer = slots.footer && <div class={bem('footer')}>{slots.footer}</div>; const Footer = slots('footer') && <div class={bem('footer')}>{slots('footer')}</div>;
return ( return (
<div class={bem()}> <div class={bem()}>
@ -76,7 +76,7 @@ export default sfc({
<div class={bem('content', { centered: this.centered })}> <div class={bem('content', { centered: this.centered })}>
{Title} {Title}
{Desc} {Desc}
{slots.tags} {slots('tags')}
<div class="van-card__bottom"> <div class="van-card__bottom">
{Price} {Price}
{OriginPrice} {OriginPrice}

View File

@ -22,29 +22,29 @@ export default sfc({
}, },
render(h) { render(h) {
const slots = this.$slots; const { slots } = this;
const showTitle = slots.title || isDef(this.title); const showTitle = slots('title') || isDef(this.title);
const showValue = slots.default || isDef(this.value); const showValue = slots() || isDef(this.value);
const Title = showTitle && ( const Title = showTitle && (
<div class={[bem('title'), this.titleClass]}> <div class={[bem('title'), this.titleClass]}>
{slots.title || <span>{this.title}</span>} {slots('title') || <span>{this.title}</span>}
{this.label && <div class={[bem('label'), this.labelClass]}>{this.label}</div>} {this.label && <div class={[bem('label'), this.labelClass]}>{this.label}</div>}
</div> </div>
); );
const Value = showValue && ( const Value = showValue && (
<div class={[bem('value', { alone: !slots.title && !this.title }), this.valueClass]}> <div class={[bem('value', { alone: !slots('title') && !this.title }), this.valueClass]}>
{slots.default || <span>{this.value}</span>} {slots() || <span>{this.value}</span>}
</div> </div>
); );
const LeftIcon = slots.icon || ( const LeftIcon = slots('icon') || (
this.icon && <Icon class={bem('left-icon')} name={this.icon} /> this.icon && <Icon class={bem('left-icon')} name={this.icon} />
); );
const arrowIcon = this.arrowDirection ? `arrow-${this.arrowDirection}` : 'arrow'; const arrowIcon = this.arrowDirection ? `arrow-${this.arrowDirection}` : 'arrow';
const RightIcon = slots['right-icon'] || ( const RightIcon = slots('right-icon') || (
this.isLink && <Icon class={bem('right-icon')} name={arrowIcon} /> this.isLink && <Icon class={bem('right-icon')} name={arrowIcon} />
); );
@ -63,7 +63,7 @@ export default sfc({
{Title} {Title}
{Value} {Value}
{RightIcon} {RightIcon}
{slots.extra} {slots('extra')}
</div> </div>
); );
} }

View File

@ -16,6 +16,6 @@ export default sfc({
}, },
render(h) { render(h) {
return <div class={bem()}>{this.$slots.default}</div>; return <div class={bem()}>{this.slots()}</div>;
} }
}); });

View File

@ -110,7 +110,7 @@ export default sfc({
<path class={bem('hover')} style={this.hoverStyle} d={PATH} /> <path class={bem('hover')} style={this.hoverStyle} d={PATH} />
<path class={bem('layer')} style={this.layerStyle} d={PATH} /> <path class={bem('layer')} style={this.layerStyle} d={PATH} />
</svg> </svg>
{this.$slots.default || (this.text && <div class={bem('text')}>{this.text}</div>)} {this.slots() || (this.text && <div class={bem('text')}>{this.text}</div>)}
</div> </div>
); );
} }

View File

@ -27,7 +27,7 @@ export default sfc({
const { span, offset } = this; const { span, offset } = this;
return ( return (
<this.tag class={bem({ [span]: span, [`offset-${offset}`]: offset })} style={this.style}> <this.tag class={bem({ [span]: span, [`offset-${offset}`]: offset })} style={this.style}>
{this.$slots.default} {this.slots()}
</this.tag> </this.tag>
); );
} }

View File

@ -116,8 +116,8 @@ export default sfc({
onClick={this.onClick} onClick={this.onClick}
{...{ props: this.$props }} {...{ props: this.$props }}
> >
{this.$slots.value} {this.slots('value')}
{CELL_SLOTS.map(slot => h('template', { slot }, this.$slots[slot]))} {CELL_SLOTS.map(slot => h('template', { slot }, this.slots(slot)))}
</Cell> </Cell>
); );
@ -129,7 +129,7 @@ export default sfc({
onTransitionend={this.onTransitionEnd} onTransitionend={this.onTransitionEnd}
> >
<div ref="content" class={bem('content')}> <div ref="content" class={bem('content')}>
{this.$slots.default} {this.slots()}
</div> </div>
</div> </div>
); );

View File

@ -27,6 +27,6 @@ export default sfc({
}, },
render(h) { render(h) {
return <div class={[bem(), 'van-hairline--top-bottom']}>{this.$slots.default}</div>; return <div class={[bem(), 'van-hairline--top-bottom']}>{this.slots()}</div>;
} }
}); });

View File

@ -68,7 +68,7 @@ export default sfc({
} }
const { title, message, messageAlign } = this; const { title, message, messageAlign } = this;
const children = this.$slots.default; const children = this.slots();
const Title = title && ( const Title = title && (
<div class={bem('header', { isolated: !message && !children })}>{title}</div> <div class={bem('header', { isolated: !message && !children })}>{title}</div>

View File

@ -167,19 +167,19 @@ export default sfc({
}, },
render(h) { render(h) {
const { type, labelAlign, $slots: slots } = this; const { type, labelAlign, slots } = this;
const showLeftIcon = slots['left-icon'] || this.leftIcon; const showLeftIcon = slots('left-icon') || this.leftIcon;
const showRightIcon = slots['right-icon'] || slots.icon || this.rightIcon || this.icon; const showRightIcon = slots('right-icon') || slots('icon') || this.rightIcon || this.icon;
const LeftIcon = showLeftIcon && ( const LeftIcon = showLeftIcon && (
<div slot="icon" class={bem('left-icon')} onClick={this.onClickLeftIcon}> <div slot="icon" class={bem('left-icon')} onClick={this.onClickLeftIcon}>
{slots['left-icon'] || <Icon name={this.leftIcon} />} {slots('left-icon') || <Icon name={this.leftIcon} />}
</div> </div>
); );
const RightIcon = showRightIcon && ( const RightIcon = showRightIcon && (
<div class={bem('right-icon')} onClick={this.onClickRightIcon}> <div class={bem('right-icon')} onClick={this.onClickRightIcon}>
{slots['right-icon'] || slots.icon || <Icon name={this.rightIcon || this.icon} />} {slots('right-icon') || slots('icon') || <Icon name={this.rightIcon || this.icon} />}
</div> </div>
); );
@ -214,12 +214,12 @@ export default sfc({
})} })}
> >
{LeftIcon} {LeftIcon}
{h('template', { slot: 'title' }, slots.label)} {h('template', { slot: 'title' }, slots('label'))}
<div class={bem('body')}> <div class={bem('body')}>
{Input} {Input}
{this.showClear && <Icon name="clear" class={bem('clear')} onTouchstart={this.onClear} />} {this.showClear && <Icon name="clear" class={bem('clear')} onTouchstart={this.onClear} />}
{RightIcon} {RightIcon}
{slots.button && <div class={bem('button')}>{slots.button}</div>} {slots('button') && <div class={bem('button')}>{slots('button')}</div>}
</div> </div>
{this.errorMessage && <div class={bem('error-message')}>{this.errorMessage}</div>} {this.errorMessage && <div class={bem('error-message')}>{this.errorMessage}</div>}
</Cell> </Cell>

View File

@ -32,7 +32,7 @@ export default sfc({
type={this.primary ? 'danger' : 'warning'} type={this.primary ? 'danger' : 'warning'}
onClick={this.onClick} onClick={this.onClick}
> >
{this.$slots.default || this.text} {this.slots() || this.text}
</Button> </Button>
); );
} }

View File

@ -25,7 +25,7 @@ export default sfc({
return ( return (
<div class={[bem(), 'van-hairline']} onClick={this.onClick}> <div class={[bem(), 'van-hairline']} onClick={this.onClick}>
<Icon class={[bem('icon'), this.iconClass]} info={this.info} name={this.icon} /> <Icon class={[bem('icon'), this.iconClass]} info={this.info} name={this.icon} />
{this.$slots.default || this.text} {this.slots() || this.text}
</div> </div>
); );
} }

View File

@ -116,10 +116,10 @@ export default sfc({
render(h) { render(h) {
return ( return (
<div class={bem()}> <div class={bem()}>
{this.$slots.default} {this.slots()}
{this.loading && ( {this.loading && (
<div class={bem('loading')}> <div class={bem('loading')}>
{this.$slots.loading || [ {this.slots('loading') || [
<Loading class={bem('loading-icon')} />, <Loading class={bem('loading-icon')} />,
<span class={bem('loading-text')}>{this.loadingText || t('loading')}</span> <span class={bem('loading-text')}>{this.loadingText || t('loading')}</span>
]} ]}

View File

@ -1,7 +1,6 @@
/** /**
* Common part of Checkbox & Radio * Common part of Checkbox & Radio
*/ */
import { useSlots } from '../utils';
import Icon from '../icon'; import Icon from '../icon';
import findParent from './find-parent'; import findParent from './find-parent';
@ -42,18 +41,18 @@ export default (parent, bem) => ({
}, },
render(h) { render(h) {
const { checked } = this; const { slots, checked } = this;
const slots = useSlots(this);
const CheckIcon = slots('icon', { checked }) || ( const CheckIcon = slots('icon', { checked }) || (
<Icon name="success" style={this.iconStyle} /> <Icon name="success" style={this.iconStyle} />
); );
const Label = slots('default') && ( const Label = slots() && (
<span <span
class={bem('label', [this.labelPosition, { disabled: this.isDisabled }])} class={bem('label', [this.labelPosition, { disabled: this.isDisabled }])}
onClick={this.onClickLabel} onClick={this.onClickLabel}
> >
{slots('default')} {slots()}
</span> </span>
); );

16
packages/mixins/slots.js Normal file
View File

@ -0,0 +1,16 @@
/**
* Use scopedSlots in Vue 2.6+
* downgrade to slots in lower version
*/
export default {
methods: {
slots(name = 'default', props) {
const { $slots, $scopedSlots } = this;
if ($scopedSlots[name]) {
return $scopedSlots[name](props);
}
return $slots[name];
}
}
};

View File

@ -106,7 +106,7 @@ export default sfc({
onAnimationend={this.onAnimationEnd} onAnimationend={this.onAnimationEnd}
onWebkitAnimationEnd={this.onAnimationEnd} onWebkitAnimationEnd={this.onAnimationEnd}
> >
{this.$slots.default || this.text} {this.slots() || this.text}
</div> </div>
</div> </div>
{iconName && <Icon class={bem('right-icon')} name={iconName} onClick={this.onClickIcon} />} {iconName && <Icon class={bem('right-icon')} name={iconName} onClick={this.onClickIcon} />}

View File

@ -127,7 +127,7 @@ export default sfc({
</li> </li>
))} ))}
{simple && ( {simple && (
<li class={bem('page-desc')}>{this.$slots.pageDesc || `${value}/${this.count}`}</li> <li class={bem('page-desc')}>{this.slots('pageDesc') || `${value}/${this.count}`}</li>
)} )}
<li <li
class={[bem('item', { disabled: value === this.count }), bem('next'), 'van-hairline']} class={[bem('item', { disabled: value === this.count }), bem('next'), 'van-hairline']}

View File

@ -149,7 +149,7 @@ export default sfc({
const Toolbar = this.showToolbar && ( const Toolbar = this.showToolbar && (
<div class={['van-hairline--top-bottom', bem('toolbar')]}> <div class={['van-hairline--top-bottom', bem('toolbar')]}>
{this.$slots.default || [ {this.slots() || [
<div class={bem('cancel')} onClick={this.onCancel}> <div class={bem('cancel')} onClick={this.onCancel}>
{this.cancelButtonText || t('cancel')} {this.cancelButtonText || t('cancel')}
</div>, </div>,

View File

@ -35,7 +35,7 @@ export default sfc({
onAfterLeave={emit('closed')} onAfterLeave={emit('closed')}
> >
<div vShow={this.value} class={bem({ [position]: position })}> <div vShow={this.value} class={bem({ [position]: position })}>
{this.$slots.default} {this.slots()}
</div> </div>
</transition> </transition>
); );

View File

@ -133,7 +133,7 @@ export default sfc({
transform: `translate3d(0,${this.height}px, 0)` transform: `translate3d(0,${this.height}px, 0)`
}; };
const Status = this.$slots[status] || [ const Status = this.slots(status) || [
(status === 'pulling' || status === 'loosing') && <div class={bem('text')}>{text}</div>, (status === 'pulling' || status === 'loosing') && <div class={bem('text')}>{text}</div>,
status === 'loading' && ( status === 'loading' && (
<div class={bem('loading')}> <div class={bem('loading')}>
@ -154,7 +154,7 @@ export default sfc({
onTouchcancel={this.onTouchEnd} onTouchcancel={this.onTouchEnd}
> >
<div class={bem('head')}>{Status}</div> <div class={bem('head')}>{Status}</div>
{this.$slots.default} {this.slots()}
</div> </div>
</div> </div>
); );

View File

@ -15,6 +15,6 @@ export default sfc({
}, },
render(h) { render(h) {
return <div class={bem()}>{this.$slots.default}</div>; return <div class={bem()}>{this.slots()}</div>;
} }
}); });

View File

@ -32,7 +32,7 @@ export default sfc({
[`justify-${justify}`]: flex && justify [`justify-${justify}`]: flex && justify
})} })}
> >
{this.$slots.default} {this.slots()}
</this.tag> </this.tag>
); );
} }

View File

@ -63,11 +63,11 @@ export default sfc({
leftIcon="search" leftIcon="search"
{...props} {...props}
> >
{h('template', { slot: 'left-icon' }, this.$slots['left-icon'])} {h('template', { slot: 'left-icon' }, this.slots('left-icon'))}
</Field> </Field>
{showAction && ( {showAction && (
<div class={bem('action')}> <div class={bem('action')}>
{this.$slots.action || <div onClick={this.onBack}>{t('cancel')}</div>} {this.slots('action') || <div onClick={this.onBack}>{t('cancel')}</div>}
</div> </div>
)} )}
</div> </div>

View File

@ -9,9 +9,9 @@ import SkuRowItem from './components/SkuRowItem';
import SkuStepper from './components/SkuStepper'; import SkuStepper from './components/SkuStepper';
import SkuMessages from './components/SkuMessages'; import SkuMessages from './components/SkuMessages';
import SkuActions from './components/SkuActions'; import SkuActions from './components/SkuActions';
import { use } from '../utils';
import { isAllSelected, isSkuChoosable, getSkuComb, getSelectedSkuValues } from './utils/skuHelper'; import { isAllSelected, isSkuChoosable, getSkuComb, getSelectedSkuValues } from './utils/skuHelper';
import { LIMIT_TYPE, UNSELECTED_SKU_VALUE_ID } from './constants'; import { LIMIT_TYPE, UNSELECTED_SKU_VALUE_ID } from './constants';
import { use, useSlots } from '../utils';
const [sfc] = use('sku'); const [sfc] = use('sku');
const { QUOTA_LIMIT } = LIMIT_TYPE; const { QUOTA_LIMIT } = LIMIT_TYPE;
@ -367,7 +367,7 @@ export default sfc({
selectedSku, selectedSku,
selectedSkuComb selectedSkuComb
}; };
const slots = name => useSlots(this)(name, slotsProps); const slots = name => this.slots(name, slotsProps);
const Header = slots('sku-header') || ( const Header = slots('sku-header') || (
<SkuHeader sku={sku} goods={goods} skuEventBus={skuEventBus} selectedSku={selectedSku}> <SkuHeader sku={sku} goods={goods} skuEventBus={skuEventBus} selectedSku={selectedSku}>

View File

@ -46,7 +46,7 @@ export default sfc({
</div> </div>
<div class={bem('goods-info')}> <div class={bem('goods-info')}>
<div class="van-sku__goods-name van-ellipsis">{this.goods.title}</div> <div class="van-sku__goods-name van-ellipsis">{this.goods.title}</div>
{this.$slots.default} {this.slots()}
<Icon <Icon
name="close" name="close"
class="van-sku__close-icon" class="van-sku__close-icon"

View File

@ -11,7 +11,7 @@ export default sfc({
return ( return (
<div class={bem()}> <div class={bem()}>
<div class={bem('title')}>{this.skuRow.k}</div> <div class={bem('title')}>{this.skuRow.k}</div>
{this.$slots.default} {this.slots()}
</div> </div>
); );
} }

View File

@ -96,7 +96,7 @@ export default sfc({
onTouchend={this.onTouchEnd} onTouchend={this.onTouchEnd}
onTouchcancel={this.onTouchEnd} onTouchcancel={this.onTouchEnd}
> >
{this.$slots.button || <div class={bem('button')} />} {this.slots('button') || <div class={bem('button')} />}
</div> </div>
</div> </div>
</div> </div>

View File

@ -30,7 +30,7 @@ export default sfc({
return ( return (
<div class={['van-hairline', bem([direction, { [status]: status }])]}> <div class={['van-hairline', bem([direction, { [status]: status }])]}>
<div class={bem('title')} style={titleStyle}> <div class={bem('title')} style={titleStyle}>
{this.$slots.default} {this.slots()}
</div> </div>
<div class={bem('circle-container')}> <div class={bem('circle-container')}>
{status !== 'process' ? ( {status !== 'process' ? (

View File

@ -28,10 +28,10 @@ export default sfc({
}, },
render(h) { render(h) {
const { icon, title, description, $slots } = this; const { icon, title, description, slots } = this;
const StatusIcon = ($slots.icon || icon) && ( const StatusIcon = (slots('icon') || icon) && (
<div class={bem('icon')}>{$slots.icon || <Icon name={icon} class={this.iconClass} />}</div> <div class={bem('icon')}>{slots('icon') || <Icon name={icon} class={this.iconClass} />}</div>
); );
const StatusMessage = ( const StatusMessage = (
@ -47,10 +47,10 @@ export default sfc({
<div class={bem('status')}> <div class={bem('status')}>
{StatusIcon} {StatusIcon}
{StatusMessage} {StatusMessage}
{$slots['message-extra']} {slots('message-extra')}
</div> </div>
)} )}
<div class={bem('items', { alone: !title && !description })}>{$slots.default}</div> <div class={bem('items', { alone: !title && !description })}>{slots()}</div>
</div> </div>
); );
} }

View File

@ -148,13 +148,13 @@ export default sfc({
> >
{this.leftWidth && ( {this.leftWidth && (
<div class={bem('left')} onClick={onClick('left', true)}> <div class={bem('left')} onClick={onClick('left', true)}>
{this.$slots.left} {this.slots('left')}
</div> </div>
)} )}
{this.$slots.default} {this.slots()}
{this.rightWidth && ( {this.rightWidth && (
<div class={bem('right')} onClick={onClick('right', true)}> <div class={bem('right')} onClick={onClick('right', true)}>
{this.$slots.right} {this.slots('right')}
</div> </div>
)} )}
</div> </div>

View File

@ -28,7 +28,7 @@ export default sfc({
return ( return (
<div class={bem()} style={style}> <div class={bem()} style={style}>
{this.$slots.default} {this.slots()}
</div> </div>
); );
} }

View File

@ -265,7 +265,7 @@ export default sfc({
const { count, activeIndicator } = this; const { count, activeIndicator } = this;
const Indicator = const Indicator =
this.$slots.indicator || this.slots('indicator') ||
(this.showIndicators && count > 1 && ( (this.showIndicators && count > 1 && (
<div class={bem('indicators', { vertical: this.vertical })} onTransitionend={stop}> <div class={bem('indicators', { vertical: this.vertical })} onTransitionend={stop}>
{Array(...Array(count)).map((empty, index) => ( {Array(...Array(count)).map((empty, index) => (
@ -288,7 +288,7 @@ export default sfc({
onTouchcancel={this.onTouchEnd} onTouchcancel={this.onTouchEnd}
onTransitionend={this.onTransitionend} onTransitionend={this.onTransitionend}
> >
{this.$slots.default} {this.slots()}
</div> </div>
{Indicator} {Indicator}
</div> </div>

View File

@ -44,10 +44,10 @@ export default sfc({
mounted() { mounted() {
const { tabs } = this.parent; const { tabs } = this.parent;
const index = this.parent.$slots.default.indexOf(this.$vnode); const index = this.parent.slots().indexOf(this.$vnode);
tabs.splice(index === -1 ? tabs.length : index, 0, this); tabs.splice(index === -1 ? tabs.length : index, 0, this);
if (this.$slots.title) { if (this.slots('title')) {
this.parent.renderTitle(this.$refs.title, this.index); this.parent.renderTitle(this.$refs.title, this.index);
} }
}, },
@ -57,11 +57,11 @@ export default sfc({
}, },
render(h) { render(h) {
const slots = this.$slots; const { slots } = this;
return ( return (
<div vShow={this.selected || this.parent.animated} class={bem('pane')}> <div vShow={this.selected || this.parent.animated} class={bem('pane')}>
{this.inited ? slots.default : h()} {this.inited ? slots() : h()}
{slots.title && <div ref="title">{slots.title}</div>} {slots('title') && <div ref="title">{slots('title')}</div>}
</div> </div>
); );
} }

View File

@ -1,4 +1,4 @@
import { use, useSlots } from '../utils'; import { use } from '../utils';
import Icon from '../icon'; import Icon from '../icon';
import Info from '../info'; import Info from '../info';
import RouterLink from '../mixins/router-link'; import RouterLink from '../mixins/router-link';
@ -37,8 +37,7 @@ export default sfc({
}, },
render(h) { render(h) {
const { icon, active } = this; const { icon, slots, active } = this;
const slots = useSlots(this);
const style = active ? { color: this.$parent.activeColor } : null; const style = active ? { color: this.$parent.activeColor } : null;
return ( return (

View File

@ -53,7 +53,7 @@ export default sfc({
style={{ zIndex: this.zIndex }} style={{ zIndex: this.zIndex }}
class={['van-hairline--top-bottom', bem({ fixed: this.fixed })]} class={['van-hairline--top-bottom', bem({ fixed: this.fixed })]}
> >
{this.$slots.default} {this.slots()}
</div> </div>
); );
} }

View File

@ -418,10 +418,10 @@ export default sfc({
<div ref="content" class={bem('content', { animated })}> <div ref="content" class={bem('content', { animated })}>
{animated ? ( {animated ? (
<div class={bem('track')} style={this.trackStyle}> <div class={bem('track')} style={this.trackStyle}>
{this.$slots.default} {this.slots()}
</div> </div>
) : ( ) : (
this.$slots.default this.slots()
)} )}
</div> </div>
</div> </div>

View File

@ -95,7 +95,7 @@ export default sfc({
return ( return (
<div class={bem()}> <div class={bem()}>
{this.$slots.default} {this.slots()}
<input <input
{ ...{ attrs: this.$attrs } } { ...{ attrs: this.$attrs } }
ref="input" ref="input"

View File

@ -1,6 +1,6 @@
import Vue from 'vue'; import Vue from 'vue';
export { use, useSlots } from './use'; export { use } from './use';
export const isServer = Vue.prototype.$isServer; export const isServer = Vue.prototype.$isServer;

View File

@ -6,12 +6,3 @@ export function use(name) {
name = 'van-' + name; name = 'van-' + name;
return [useSfc(name), useBem(name), useI18n(name)]; return [useSfc(name), useBem(name), useI18n(name)];
} }
export function useSlots({ $slots, $scopedSlots }) {
return (name, props) => {
if ($scopedSlots[name]) {
return $scopedSlots[name](props);
}
return $slots[name];
};
}

View File

@ -3,6 +3,7 @@
*/ */
import '../../locale'; import '../../locale';
import { camelize } from '..'; import { camelize } from '..';
import SlotsMixin from '../../mixins/slots';
const arrayProp = { const arrayProp = {
type: Array, type: Array,
@ -50,6 +51,8 @@ function functional(sfc) {
export default name => (sfc, isFunctional) => { export default name => (sfc, isFunctional) => {
sfc.name = name; sfc.name = name;
sfc.install = install; sfc.install = install;
sfc.mixins = sfc.mixins || [];
sfc.mixins.push(SlotsMixin);
if (sfc.props) { if (sfc.props) {
defaultProps(sfc.props); defaultProps(sfc.props);

View File

@ -10274,10 +10274,10 @@ vue-router@^3.0.2:
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.0.2.tgz#dedc67afe6c4e2bc25682c8b1c2a8c0d7c7e56be" resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.0.2.tgz#dedc67afe6c4e2bc25682c8b1c2a8c0d7c7e56be"
integrity sha512-opKtsxjp9eOcFWdp6xLQPLmRGgfM932Tl56U9chYTnoWqKxQ8M20N7AkdEbM5beUh6wICoFGYugAX9vQjyJLFg== integrity sha512-opKtsxjp9eOcFWdp6xLQPLmRGgfM932Tl56U9chYTnoWqKxQ8M20N7AkdEbM5beUh6wICoFGYugAX9vQjyJLFg==
vue-server-renderer@^2.6.1: vue-server-renderer@^2.6.2:
version "2.6.1" version "2.6.2"
resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.6.1.tgz#a5076076ea1b1cd517e8556ea5362232d042606f" resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.6.2.tgz#89faa6d87e94f9333276a4ee9cd39bece97059db"
integrity sha512-fpKjWYYqKceiJIJGigTcXBabbMi6g3KANhf64Gn4AzFo7bS/wzZkqCQYLRMjAjj6LQzfa7sPJBPSpMdpq/UAfg== integrity sha512-UAAKbYhcT9WRP7L4aRR/c6e/GXBj5lwR9H8AQ+b/lbwVwMauHyYNdhQzFmLFZfujNAjZK6+mQQVtdMoa2J8Y5g==
dependencies: dependencies:
chalk "^1.1.3" chalk "^1.1.3"
hash-sum "^1.0.2" hash-sum "^1.0.2"
@ -10296,10 +10296,10 @@ vue-style-loader@^4.1.0:
hash-sum "^1.0.2" hash-sum "^1.0.2"
loader-utils "^1.0.2" loader-utils "^1.0.2"
vue-template-compiler@2.6.1: vue-template-compiler@2.6.2:
version "2.6.1" version "2.6.2"
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.1.tgz#b6a1b622acc602a556dcca2c1bf5d05afc7ac077" resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.2.tgz#6230abf7ca92d565b7471c0cc3f54d5b12aa48e7"
integrity sha512-lHEnUkFcTPd99CprdTdA43hj29V1UlJiefCXWP3jJMjrz6wD1FQWEOCiCjwMXDEBstCWYscVjERtwzL0mJ1lJA== integrity sha512-2dBKNCtBPdx1TFef7T4zwF8IjOx2xbMNryCtFzneP+XIonJwOtnkq4s1mhKv8W79gXcGINQWtuaxituGAcuSnA==
dependencies: dependencies:
de-indent "^1.0.2" de-indent "^1.0.2"
he "^1.1.0" he "^1.1.0"
@ -10314,10 +10314,10 @@ vue-template-es2015-compiler@^1.8.2:
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.8.2.tgz#dd73e80ba58bb65dd7a8aa2aeef6089cf6116f2a" resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.8.2.tgz#dd73e80ba58bb65dd7a8aa2aeef6089cf6116f2a"
integrity sha512-cliV19VHLJqFUYbz/XeWXe5CO6guzwd0yrrqqp0bmjlMP3ZZULY7fu8RTC4+3lmHwo6ESVDHFDsvjB15hcR5IA== integrity sha512-cliV19VHLJqFUYbz/XeWXe5CO6guzwd0yrrqqp0bmjlMP3ZZULY7fu8RTC4+3lmHwo6ESVDHFDsvjB15hcR5IA==
vue@2.6.1: vue@2.6.2:
version "2.6.1" version "2.6.2"
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.1.tgz#2167a19e6489ff8082388f7c5f5caf56a32ddba9" resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.2.tgz#1cc9c9c8f7ba8df45e9b97c284947de78b76301c"
integrity sha512-ka6pgKZSa44+/11g+sD99Akajt0GceTnT8tagqLrQovXptgwaiLaEOHzMA/FLR07lGIfIR2UTHb69bTRBN71dA== integrity sha512-NZAb0H+t3/99g2nygURcEJ+ncvzNLPiEiFI5MGhc1Cjsw5uYprF+Ol7SOd1RXPcmVVzK7jUBl0th2tNgt+VQDg==
w3c-hr-time@^1.0.1: w3c-hr-time@^1.0.1:
version "1.0.1" version "1.0.1"