[improvement] Sku: jsx (#2666)

This commit is contained in:
neverland 2019-02-01 21:50:47 +08:00 committed by GitHub
parent 7ee383129c
commit 3958a42484
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 458 additions and 526 deletions

View File

@ -1,132 +1,3 @@
<template>
<popup
v-if="!isSkuEmpty"
v-model="show"
position="bottom"
class="van-sku-container"
:close-on-click-overlay="closeOnClickOverlay"
:get-container="getContainer"
>
<!-- sku-header -->
<slot
name="sku-header"
:sku-event-bus="skuEventBus"
:selected-sku="selectedSku"
:selected-sku-comb="selectedSkuComb"
>
<sku-header
:sku-event-bus="skuEventBus"
:selected-sku="selectedSku"
:goods="goods"
:sku="sku"
>
<slot
name="sku-header-price"
:price="price"
:selected-sku-comb="selectedSkuComb"
>
<div class="van-sku__goods-price">
<span class="van-sku__price-symbol"></span>
<span
v-text="price"
class="van-sku__price-num"
/>
</div>
</slot>
</sku-header>
</slot>
<div
class="van-sku-body"
:style="bodyStyle"
>
<!-- sku-body-top -->
<slot
name="sku-body-top"
:selected-sku="selectedSku"
:sku-event-bus="skuEventBus"
/>
<!-- sku-group -->
<slot
name="sku-group"
:selected-sku="selectedSku"
:sku-event-bus="skuEventBus"
>
<div
v-if="hasSku"
:class="skuGroupClass"
>
<sku-row
v-for="(skuTreeItem, index) in skuTree"
:key="index"
:sku-row="skuTreeItem"
>
<sku-row-item
v-for="(skuValue, valueIndex) in skuTreeItem.v"
:key="valueIndex"
:sku-key-str="skuTreeItem.k_s"
:sku-value="skuValue"
:sku-event-bus="skuEventBus"
:selected-sku="selectedSku"
:sku-list="sku.list"
/>
</sku-row>
</div>
</slot>
<!-- extra-sku-group -->
<slot
name="extra-sku-group"
:sku-event-bus="skuEventBus"
/>
<!-- sku-stepper -->
<slot
name="sku-stepper"
:sku-event-bus="skuEventBus"
:selected-sku="selectedSku"
:selected-sku-comb="selectedSkuComb"
:selected-num="selectedNum"
>
<sku-stepper
ref="skuStepper"
:sku-event-bus="skuEventBus"
:selected-sku="selectedSku"
:selected-sku-comb="selectedSkuComb"
:selected-num="selectedNum"
:stepper-title="stepperTitle"
:sku-stock-num="sku.stock_num"
:hide-quota-text="hideQuotaText"
:quota="quota"
:quota-used="quotaUsed"
:disable-stepper-input="disableStepperInput"
:hide-stock="hideStock"
:custom-stepper-config="customStepperConfig"
@change="$emit('stepper-change', $event)"
/>
</slot>
<!-- sku-messages -->
<slot name="sku-messages">
<sku-messages
ref="skuMessages"
:goods-id="goodsId"
:message-config="messageConfig"
:messages="sku.messages"
/>
</slot>
</div>
<!-- sku-actions -->
<slot
name="sku-actions"
:sku-event-bus="skuEventBus"
>
<sku-actions
:sku-event-bus="skuEventBus"
:buy-text="buyText"
:show-add-cart-btn="showAddCartBtn"
/>
</slot>
</popup>
</template>
<script>
/* eslint-disable camelcase */ /* eslint-disable camelcase */
import Vue from 'vue'; import Vue from 'vue';
import Popup from '../popup'; import Popup from '../popup';
@ -138,30 +9,14 @@ 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 { import { isAllSelected, isSkuChoosable, getSkuComb, getSelectedSkuValues } from './utils/skuHelper';
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 create from '../utils/create'; import { use, useSlots } from '../utils';
const [sfc] = use('sku');
const { QUOTA_LIMIT } = LIMIT_TYPE; const { QUOTA_LIMIT } = LIMIT_TYPE;
export default create({ export default sfc({
name: 'sku',
components: {
Popup,
SkuHeader,
SkuRow,
SkuRowItem,
SkuStepper,
SkuMessages,
SkuActions
},
props: { props: {
sku: Object, sku: Object,
goods: Object, goods: Object,
@ -221,10 +76,7 @@ export default create({
show(val) { show(val) {
this.$emit('input', val); this.$emit('input', val);
if (!val) { if (!val) {
const selectedSkuValues = getSelectedSkuValues( const selectedSkuValues = getSelectedSkuValues(this.sku.tree, this.selectedSku);
this.sku.tree,
this.selectedSku
);
this.$emit('sku-close', { this.$emit('sku-close', {
selectedSkuValues, selectedSkuValues,
@ -374,15 +226,11 @@ export default create({
}, },
getSkuCartMessages() { getSkuCartMessages() {
return this.$refs.skuMessages return this.$refs.skuMessages ? this.$refs.skuMessages.getCartMessages() : {};
? this.$refs.skuMessages.getCartMessages()
: {};
}, },
validateSkuMessages() { validateSkuMessages() {
return this.$refs.skuMessages return this.$refs.skuMessages ? this.$refs.skuMessages.validateMessages() : '';
? this.$refs.skuMessages.validateMessages()
: '';
}, },
validateSku() { validateSku() {
@ -493,6 +341,121 @@ export default create({
cartMessages: this.getSkuCartMessages() cartMessages: this.getSkuCartMessages()
}; };
} }
},
render(h) {
if (this.isSkuEmpty) {
return;
}
const {
sku,
goods,
price,
skuEventBus,
selectedSku,
selectedNum,
stepperTitle,
hideQuotaText,
selectedSkuComb
} = this;
const slotsProps = {
price,
selectedNum,
skuEventBus,
selectedSku,
selectedSkuComb
};
const slots = name => useSlots(this)(name, slotsProps);
const Header = slots('sku-header') || (
<SkuHeader sku={sku} goods={goods} skuEventBus={skuEventBus} selectedSku={selectedSku}>
{slots('sku-header-price') || (
<div class="van-sku__goods-price">
<span class="van-sku__price-symbol"></span>
<span class="van-sku__price-num">{price}</span>
</div>
)}
</SkuHeader>
);
const Group =
slots('sku-group') ||
(this.hasSku && (
<div class={this.skuGroupClass}>
{this.skuTree.map(skuTreeItem => (
<SkuRow skuRow={skuTreeItem}>
{skuTreeItem.v.map(skuValue => (
<SkuRowItem
skuList={sku.list}
skuValue={skuValue}
selectedSku={selectedSku}
skuEventBus={skuEventBus}
skuKeyStr={skuTreeItem.k_s}
/>
))}
</SkuRow>
))}
</div>
));
const Stepper = slots('sku-stepper') || (
<SkuStepper
ref="skuStepper"
quota={this.quota}
hideStock={this.hideStock}
quotaUsed={this.quotaUsed}
skuEventBus={skuEventBus}
selectedNum={selectedNum}
selectedSku={selectedSku}
stepperTitle={stepperTitle}
skuStockNum={sku.stock_num}
hideQuotaText={hideQuotaText}
selectedSkuComb={selectedSkuComb}
disableStepperInput={this.disableStepperInput}
customStepperConfig={this.customStepperConfig}
onChange={event => {
this.$emit('stepper-change', event);
}}
/>
);
const Messages = slots('sku-messages') || (
<SkuMessages
ref="skuMessages"
goodsId={this.goodsId}
messageConfig={this.messageConfig}
messages={sku.messages}
/>
);
const Actions = slots('sku-actions') || (
<SkuActions
buyText={this.buyText}
skuEventBus={skuEventBus}
showAddCartBtn={this.showAddCartBtn}
/>
);
return (
<Popup
vModel={this.show}
position="bottom"
class="van-sku-container"
getContainer={this.getContainer}
closeOnClickOverlay={this.closeOnClickOverlay}
>
{Header}
<div class="van-sku-body" style={this.bodyStyle}>
{slots('sku-body-top')}
{Group}
{slots('extra-sku-group')}
{Stepper}
{Messages}
</div>
{Actions}
</Popup>
);
} }
}); });
</script>

View File

@ -0,0 +1,32 @@
import { use } from '../../utils';
import Button from '../../button';
const [sfc, bem] = use('sku-actions');
export default sfc({
props: {
buyText: String,
skuEventBus: Object,
showAddCartBtn: Boolean
},
render(h) {
const emit = name => () => {
this.skuEventBus.$emit('sku:addCart');
};
return (
<div class={bem()}>
{this.showAddCartBtn && (
<Button bottomAction text="加入购物车" onClick={emit('sku:addCart')} />
)}
<Button
type="primary"
bottomAction
text={this.buyText || '立即购买'}
onClick={emit('sku:buy')}
/>
</div>
);
}
});

View File

@ -1,35 +0,0 @@
<template>
<div :class="b()">
<van-button
v-if="showAddCartBtn"
bottom-action
text="加入购物车"
@click="skuEventBus.$emit('sku:addCart')"
/>
<van-button
type="primary"
bottom-action
:text="buyText || '立即购买'"
@click="skuEventBus.$emit('sku:buy')"
/>
</div>
</template>
<script>
import VanButton from '../../button';
import create from '../../utils/create';
export default create({
name: 'sku-actions',
components: {
VanButton
},
props: {
buyText: String,
skuEventBus: Object,
showAddCartBtn: Boolean
}
});
</script>

View File

@ -0,0 +1,61 @@
import { use } from '../../utils';
import Icon from '../../icon';
const [sfc, bem] = use('sku-header');
export default sfc({
props: {
sku: Object,
goods: Object,
skuEventBus: Object,
selectedSku: Object
},
computed: {
goodsImg() {
const s1Id = this.selectedSku.s1;
const skuImg = this.getSkuImg(s1Id);
// 优先使用选中 sku 的图片
return skuImg || this.goods.picture;
}
},
methods: {
getSkuImg(id) {
if (!id) return;
// skuImg 挂载在 skuTree 中 s1 上
const treeItem = this.sku.tree.filter(item => item.k_s === 's1')[0] || {};
if (!treeItem.v) return;
const matchedSku = treeItem.v.filter(skuValue => skuValue.id === id)[0];
if (matchedSku) return matchedSku.imgUrl || matchedSku.img_url;
},
previewImage() {
this.skuEventBus.$emit('sku:previewImage', this.goodsImg);
}
},
render(h) {
return (
<div class={[bem(), 'van-hairline--bottom']}>
<div class={bem('img-wrap')} onClick={this.previewImage}>
<img src={this.goodsImg} />
</div>
<div class={bem('goods-info')}>
<div class="van-sku__goods-name van-ellipsis">{this.goods.title}</div>
{this.$slots.default}
<Icon
name="close"
class="van-sku__close-icon"
onClick={() => {
this.skuEventBus.$emit('sku:close');
}}
/>
</div>
</div>
);
}
});

View File

@ -1,68 +0,0 @@
<template>
<div
:class="b()"
class="van-hairline--bottom"
>
<div
:class="b('img-wrap')"
@click="previewImage"
>
<img :src="goodsImg">
</div>
<div :class="b('goods-info')">
<div
v-text="goods.title"
class="van-sku__goods-name van-ellipsis"
/>
<!-- price display area -->
<slot />
<icon
name="close"
class="van-sku__close-icon"
@click="skuEventBus.$emit('sku:close')"
/>
</div>
</div>
</template>
<script>
import create from '../../utils/create';
export default create({
name: 'sku-header',
props: {
sku: Object,
goods: Object,
skuEventBus: Object,
selectedSku: Object
},
computed: {
goodsImg() {
const s1Id = this.selectedSku.s1;
const skuImg = this.getSkuImg(s1Id);
// 使sku
return skuImg || this.goods.picture;
}
},
methods: {
getSkuImg(id) {
if (!id) return;
// skuImgskuTrees1sku
const treeItem = this.sku.tree.filter(item => item.k_s === 's1')[0] || {};
if (!treeItem.v) return;
const matchedSku = treeItem.v.filter(skuValue => skuValue.id === id)[0];
if (matchedSku) return (matchedSku.imgUrl || matchedSku.img_url);
},
previewImage() {
this.skuEventBus.$emit('sku:previewImage', this.goodsImg);
}
}
});
</script>

View File

@ -0,0 +1,103 @@
import { use } from '../../utils';
import Icon from '../../icon';
import Loading from '../../loading';
import Uploader from '../../uploader';
const [sfc, bem] = use('sku-img-uploader');
export default sfc({
props: {
value: String,
uploadImg: Function,
maxSize: {
type: Number,
default: 6
}
},
data() {
return {
// 正在上传的图片 base64
paddingImg: ''
};
},
computed: {
imgList() {
return this.value && !this.paddingImg ? [this.value] : [];
}
},
methods: {
afterReadFile(file) {
// 上传文件
this.paddingImg = file.content;
this.uploadImg(file.file, file.content)
.then(img => {
this.$emit('input', img);
this.$nextTick(() => {
this.paddingImg = '';
});
})
.catch(() => {
this.paddingImg = '';
});
},
onOversize() {
this.$toast(`最大可上传图片为${this.maxSize}MB请尝试压缩图片尺寸`);
}
},
render(h) {
const { imgList, paddingImg } = this;
const ImageList = (paddingImg || imgList.length > 0) && (
<div class="van-clearfix">
{imgList.map(img => (
<div class={bem('img')}>
<img src={img} />
<Icon
name="clear"
class={bem('delete')}
onClick={() => {
this.$emit('input', '');
}}
/>
</div>
))}
{paddingImg && (
<div class={bem('img')}>
<img src={paddingImg} />
<Loading type="spinner" class={bem('uploading')} />
</div>
)}
</div>
);
return (
<div class={bem()}>
<Uploader
disabled={!!paddingImg}
afterRead={this.afterReadFile}
maxSize={this.maxSize * 1024 * 1024}
onOversize={this.onOversize}
>
<div class={bem('header')}>
{paddingImg ? (
<div>正在上传...</div>
) : (
[
<Icon name="photograph" />,
<span class="label">{this.value ? '重拍' : '拍照'} </span>,
<Icon name="photo" />,
<span class="label">{this.value ? '重新选择照片' : '选择照片'}</span>
]
)}
</div>
</Uploader>
{ImageList}
</div>
);
}
});

View File

@ -1,104 +0,0 @@
<template>
<div :class="b()">
<!-- 头部 -->
<van-uploader
:disabled="!!paddingImg"
:after-read="afterReadFile"
:max-size="maxSize * 1024 * 1024"
@oversize="onOversize"
>
<div :class="b('header')">
<div v-if="paddingImg">正在上传...</div>
<template v-else>
<icon name="photograph" />
<span class="label">{{ value ? '重拍' : '拍照' }}</span>
<icon name="photo" />
<span class="label">{{ value ? '重新选择照片' : '选择照片' }}</span>
</template>
</div>
</van-uploader>
<!-- 图片列表区域 -->
<div
v-if="paddingImg || imgList.length > 0"
class="van-clearfix"
>
<!-- 已有的图片,图片右上角显示删除按钮 -->
<div
v-for="img in imgList"
:class="b('img')"
>
<img :src="img">
<icon
name="clear"
:class="b('delete')"
@click="$emit('input', '')"
/>
</div>
<!-- 正在上传的图片,有上传等待提示 -->
<div
v-if="paddingImg"
:class="b('img')"
>
<img :src="paddingImg">
<loading
type="spinner"
:class="b('uploading')"
/>
</div>
</div>
</div>
</template>
<script>
import VanUploader from '../../uploader';
import create from '../../utils/create';
export default create({
name: 'sku-img-uploader',
components: {
VanUploader
},
props: {
value: String,
uploadImg: Function,
maxSize: {
type: Number,
default: 6
}
},
data() {
return {
// base 64
paddingImg: ''
};
},
computed: {
imgList() {
return this.value && !this.paddingImg ? [this.value] : [];
}
},
methods: {
afterReadFile(file) {
//
this.paddingImg = file.content;
this.uploadImg(file.file, file.content).then(img => {
this.$emit('input', img);
this.$nextTick(() => {
this.paddingImg = '';
});
}).catch(() => {
this.paddingImg = '';
});
},
onOversize() {
this.$toast(`最大可上传图片为${this.maxSize}MB请尝试压缩图片尺寸`);
}
}
});
</script>

View File

@ -1,41 +1,13 @@
<template> import { use } from '../../utils';
<cell-group :class="b()"> import Cell from '../../cell';
<template v-for="(message, index) in messages"> import CellGroup from '../../cell-group';
<cell
v-if="message.type === 'image'"
:class="b('image-cell')"
label="仅限一张"
:key="`${goodsId}-${index}`"
:required="message.required == '1'"
:title="message.name"
>
<sku-img-uploader
v-model="messageValues[index].value"
:upload-img="messageConfig.uploadImg"
:max-size="messageConfig.uploadMaxSize"
/>
</cell>
<field
v-else
v-model="messageValues[index].value"
maxlength="200"
:key="`${goodsId}-${index}`"
:required="message.required == '1'"
:label="message.name"
:placeholder="getPlaceholder(message)"
:type="getType(message)"
/>
</template>
</cell-group>
</template>
<script>
import create from '../../utils/create';
import Field from '../../field'; import Field from '../../field';
import validateEmail from '../../utils/validate/email'; import validateEmail from '../../utils/validate/email';
import validateNumber from '../../utils/validate/number'; import validateNumber from '../../utils/validate/number';
import SkuImgUploader from './SkuImgUploader'; import SkuImgUploader from './SkuImgUploader';
const [sfc, bem] = use('sku-messages');
const PLACEHOLDER = { const PLACEHOLDER = {
id_no: '输入身份证号码', id_no: '输入身份证号码',
text: '输入文本', text: '输入文本',
@ -47,14 +19,7 @@ const PLACEHOLDER = {
mobile: '输入手机号码' mobile: '输入手机号码'
}; };
export default create({ export default sfc({
name: 'sku-messages',
components: {
SkuImgUploader,
Field
},
props: { props: {
messages: Array, messages: Array,
messageConfig: Object, messageConfig: Object,
@ -73,12 +38,6 @@ export default create({
} }
}, },
computed: {
messagePlaceholderMap() {
return this.messageConfig.placeholderMap || {};
}
},
methods: { methods: {
resetMessageValues(messages) { resetMessageValues(messages) {
return (messages || []).map(() => ({ value: '' })); return (messages || []).map(() => ({ value: '' }));
@ -125,7 +84,8 @@ export default create({
getPlaceholder(message) { getPlaceholder(message) {
const type = +message.multiple === 1 ? 'textarea' : message.type; const type = +message.multiple === 1 ? 'textarea' : message.type;
return this.messagePlaceholderMap[type] || PLACEHOLDER[type]; const map = this.messageConfig.placeholderMap || {};
return map[type] || PLACEHOLDER[type];
}, },
validateMessages() { validateMessages() {
@ -137,7 +97,7 @@ export default create({
if (value === '') { if (value === '') {
// 必填字段的校验 // 必填字段的校验
if (message.required == '1') { // eslint-disable-line if (String(message.required) === '1') { // eslint-disable-line
const textType = message.type === 'image' const textType = message.type === 'image'
? '请上传' ? '请上传'
: '请填写'; : '请填写';
@ -159,6 +119,37 @@ export default create({
} }
} }
} }
},
render(h) {
return (
<CellGroup class={bem()}>
{this.messages.map((message, index) => (message.type === 'image' ? (
<Cell
class={bem('image-cell')}
label="仅限一张"
title={message.name}
key={`${this.goodsId}-${index}`}
required={String(message.required) === '1'}
>
<SkuImgUploader
vModel={this.messageValues[index].value}
uploadImg={this.messageConfig.uploadImg}
maxSize={this.messageConfig.uploadMaxSize}
/>
</Cell>
) : (
<Field
vModel={this.messageValues[index].value}
maxlength="200"
label={message.name}
key={`${this.goodsId}-${index}`}
required={String(message.required) === '1'}
placeholder={this.getPlaceholder(message)}
type={this.getType(message)}
/>
)))}
</CellGroup>
);
} }
}); });
</script>

View File

@ -0,0 +1,18 @@
import { use } from '../../utils';
const [sfc, bem] = use('sku-row');
export default sfc({
props: {
skuRow: Object
},
render(h) {
return (
<div class={bem()}>
<div class={bem('title')}>{this.skuRow.k}</div>
{this.$slots.default}
</div>
);
}
});

View File

@ -1,18 +0,0 @@
<template>
<div :class="b()">
<div :class="b('title')">{{ skuRow.k }}</div>
<slot />
</div>
</template>
<script>
import create from '../../utils/create';
export default create({
name: 'sku-row',
props: {
skuRow: Object
}
});
</script>

View File

@ -0,0 +1,53 @@
import { use } from '../../utils';
import { isSkuChoosable } from '../utils/skuHelper';
const [sfc] = use('sku-row-item');
export default sfc({
props: {
skuList: Array,
skuValue: Object,
skuKeyStr: String,
skuEventBus: Object,
selectedSku: Object
},
computed: {
choosable() {
return isSkuChoosable(this.skuList, this.selectedSku, {
key: this.skuKeyStr,
valueId: this.skuValue.id
});
}
},
methods: {
onSelect() {
if (this.choosable) {
this.skuEventBus.$emit('sku:select', {
...this.skuValue,
skuKeyStr: this.skuKeyStr
});
}
}
},
render(h) {
const choosed = this.skuValue.id === this.selectedSku[this.skuKeyStr];
return (
<span
class={[
'van-sku-row__item',
{
'van-sku-row__item--active': choosed,
'van-sku-row__item--disabled': !this.choosable
}
]}
onClick={this.onSelect}
>
{this.skuValue.name}
</span>
);
}
});

View File

@ -1,52 +0,0 @@
<template>
<span
v-text="skuValue.name"
class="van-sku-row__item"
:class="{
'van-sku-row__item--active': isChoosed,
'van-sku-row__item--disabled': !isChoosable
}"
@click="onSelect"
/>
</template>
<script>
import create from '../../utils/create';
import { isSkuChoosable } from '../utils/skuHelper';
export default create({
name: 'sku-row-item',
props: {
skuEventBus: Object,
skuValue: Object,
skuList: Array,
selectedSku: Object,
skuKeyStr: String
},
computed: {
isChoosed() {
return this.skuValue.id === this.selectedSku[this.skuKeyStr];
},
isChoosable() {
return isSkuChoosable(this.skuList, this.selectedSku, {
key: this.skuKeyStr,
valueId: this.skuValue.id
});
}
},
methods: {
onSelect() {
if (this.isChoosable) {
this.skuEventBus.$emit('sku:select', {
...this.skuValue,
skuKeyStr: this.skuKeyStr
});
}
}
}
});
</script>

View File

@ -1,55 +1,22 @@
<template> import { use } from '../../utils';
<div class="van-sku-stepper-stock">
<div class="van-sku-stepper-container">
<div class="van-sku__stepper-title">{{ stepperTitle || '购买数量' }}</div>
<stepper
class="van-sku__stepper"
v-model="currentNum"
:min="1"
:max="stepperLimit"
:disable-input="disableStepperInput"
@overlimit="onOverLimit"
@change="onChange"
/>
</div>
<div
v-if="!hideStock"
v-text="stockText"
class="van-sku__stock"
/>
<div
v-if="!hideQuotaText && quotaText"
v-text="quotaText"
class="van-sku__quota"
/>
</div>
</template>
<script>
import create from '../../utils/create';
import Stepper from '../../stepper'; import Stepper from '../../stepper';
import { LIMIT_TYPE } from '../constants'; import { LIMIT_TYPE } from '../constants';
const [sfc] = use('sku-stepper');
const { QUOTA_LIMIT, STOCK_LIMIT } = LIMIT_TYPE; const { QUOTA_LIMIT, STOCK_LIMIT } = LIMIT_TYPE;
export default create({ export default sfc({
name: 'sku-stepper',
components: {
Stepper
},
props: { props: {
quota: Number, quota: Number,
hideQuotaText: Boolean,
quotaUsed: Number, quotaUsed: Number,
hideStock: Boolean, hideStock: Boolean,
skuEventBus: Object, skuEventBus: Object,
skuStockNum: Number, skuStockNum: Number,
selectedSku: Object, selectedSku: Object,
selectedSkuComb: Object,
selectedNum: Number, selectedNum: Number,
stepperTitle: String, stepperTitle: String,
hideQuotaText: Boolean,
selectedSkuComb: Object,
disableStepperInput: Boolean, disableStepperInput: Boolean,
customStepperConfig: Object customStepperConfig: Object
}, },
@ -142,6 +109,27 @@ export default create({
handleStepperChange && handleStepperChange(currentValue); handleStepperChange && handleStepperChange(currentValue);
this.$emit('change', currentValue); this.$emit('change', currentValue);
} }
},
render(h) {
return (
<div class="van-sku-stepper-stock">
<div class="van-sku-stepper-container">
<div class="van-sku__stepper-title">{this.stepperTitle || '购买数量'}</div>
<Stepper
vModel={this.currentNum}
class="van-sku__stepper"
max={this.stepperLimit}
disableInput={this.disableStepperInput}
onOverlimit={this.onOverLimit}
onChange={this.onChange}
/>
</div>
{!this.hideStock && <div class="van-sku__stock">{this.stockText}</div>}
{!this.hideQuotaText && this.quotaText && (
<div class="van-sku__quota">{this.quotaText}</div>
)}
</div>
);
} }
}); });
</script>