mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
[improvement] Picker: jsx (#2613)
This commit is contained in:
parent
30159884b4
commit
6505ae7705
@ -53,10 +53,8 @@ exports[`renders demo correctly 1`] = `
|
||||
<div class="van-picker van-area">
|
||||
<div class="van-hairline--top-bottom van-picker__toolbar">
|
||||
<div class="van-picker__cancel">取消</div>
|
||||
<!---->
|
||||
<div class="van-picker__confirm">确认</div>
|
||||
</div>
|
||||
<!---->
|
||||
<div class="van-picker__columns" style="height:220px;">
|
||||
<div class="van-picker-column" style="height:220px;">
|
||||
<ul style="transition:0ms;transform:translate3d(0, 88px, 0);line-height:44px;"></ul>
|
||||
|
@ -35,7 +35,6 @@ exports[`create a AddressEdit 1`] = `
|
||||
<div class="van-picker van-area">
|
||||
<div class="van-hairline--top-bottom van-picker__toolbar">
|
||||
<div class="van-picker__cancel">取消</div>
|
||||
<!---->
|
||||
<div class="van-picker__confirm">确认</div>
|
||||
</div>
|
||||
<div class="van-picker__loading">
|
||||
@ -109,10 +108,8 @@ exports[`create a AddressEdit with props 1`] = `
|
||||
<div class="van-picker van-area">
|
||||
<div class="van-hairline--top-bottom van-picker__toolbar">
|
||||
<div class="van-picker__cancel">取消</div>
|
||||
<!---->
|
||||
<div class="van-picker__confirm">确认</div>
|
||||
</div>
|
||||
<!---->
|
||||
<div class="van-picker__columns" style="height:220px;">
|
||||
<div class="van-picker-column" style="height:220px;">
|
||||
<ul style="transition:0ms;transform:translate3d(0, 88px, 0);line-height:44px;"></ul>
|
||||
|
@ -6,10 +6,8 @@ exports[`renders demo correctly 1`] = `
|
||||
<div class="van-picker van-area">
|
||||
<div class="van-hairline--top-bottom van-picker__toolbar">
|
||||
<div class="van-picker__cancel">取消</div>
|
||||
<!---->
|
||||
<div class="van-picker__confirm">确认</div>
|
||||
</div>
|
||||
<!---->
|
||||
<div class="van-picker__columns" style="height:220px;">
|
||||
<div class="van-picker-column" style="height:220px;">
|
||||
<ul style="transition:0ms;transform:translate3d(0, 88px, 0);line-height:44px;"></ul>
|
||||
@ -28,10 +26,8 @@ exports[`renders demo correctly 1`] = `
|
||||
<div class="van-picker van-area">
|
||||
<div class="van-hairline--top-bottom van-picker__toolbar">
|
||||
<div class="van-picker__cancel">取消</div>
|
||||
<!---->
|
||||
<div class="van-picker__confirm">确认</div>
|
||||
</div>
|
||||
<!---->
|
||||
<div class="van-picker__columns" style="height:220px;">
|
||||
<div class="van-picker-column" style="height:220px;">
|
||||
<ul style="transition:0ms;transform:translate3d(0, 88px, 0);line-height:44px;"></ul>
|
||||
@ -53,7 +49,6 @@ exports[`renders demo correctly 1`] = `
|
||||
<div class="van-ellipsis van-picker__title">标题</div>
|
||||
<div class="van-picker__confirm">确认</div>
|
||||
</div>
|
||||
<!---->
|
||||
<div class="van-picker__columns" style="height:220px;">
|
||||
<div class="van-picker-column" style="height:220px;">
|
||||
<ul style="transition:0ms;transform:translate3d(0, 88px, 0);line-height:44px;"></ul>
|
||||
|
@ -4,10 +4,8 @@ exports[`change option 1`] = `
|
||||
<div class="van-picker van-area">
|
||||
<div class="van-hairline--top-bottom van-picker__toolbar">
|
||||
<div class="van-picker__cancel">取消</div>
|
||||
<!---->
|
||||
<div class="van-picker__confirm">确认</div>
|
||||
</div>
|
||||
<!---->
|
||||
<div class="van-picker__columns" style="height: 220px;">
|
||||
<div class="van-picker-column" style="height: 220px;">
|
||||
<ul style="transform: translate3d(0, 88px, 0); line-height: 44px;"></ul>
|
||||
@ -27,10 +25,8 @@ exports[`change option 2`] = `
|
||||
<div class="van-picker van-area">
|
||||
<div class="van-hairline--top-bottom van-picker__toolbar">
|
||||
<div class="van-picker__cancel">取消</div>
|
||||
<!---->
|
||||
<div class="van-picker__confirm">确认</div>
|
||||
</div>
|
||||
<!---->
|
||||
<div class="van-picker__columns" style="height: 220px;">
|
||||
<div class="van-picker-column" style="height: 220px;">
|
||||
<ul style="transform: translate3d(0, 44px, 0); line-height: 44px;">
|
||||
@ -59,10 +55,8 @@ exports[`change option 3`] = `
|
||||
<div class="van-picker van-area">
|
||||
<div class="van-hairline--top-bottom van-picker__toolbar">
|
||||
<div class="van-picker__cancel">取消</div>
|
||||
<!---->
|
||||
<div class="van-picker__confirm">确认</div>
|
||||
</div>
|
||||
<!---->
|
||||
<div class="van-picker__columns" style="height: 220px;">
|
||||
<div class="van-picker-column" style="height: 220px;">
|
||||
<ul style="transform: translate3d(0, 44px, 0); line-height: 44px;">
|
||||
@ -91,10 +85,8 @@ exports[`reset method 1`] = `
|
||||
<div class="van-picker van-area">
|
||||
<div class="van-hairline--top-bottom van-picker__toolbar">
|
||||
<div class="van-picker__cancel">取消</div>
|
||||
<!---->
|
||||
<div class="van-picker__confirm">确认</div>
|
||||
</div>
|
||||
<!---->
|
||||
<div class="van-picker__columns" style="height: 220px;">
|
||||
<div class="van-picker-column" style="height: 220px;">
|
||||
<ul style="transform: translate3d(0, 44px, 0); line-height: 44px;">
|
||||
@ -122,10 +114,8 @@ exports[`reset method 2`] = `
|
||||
<div class="van-picker van-area">
|
||||
<div class="van-hairline--top-bottom van-picker__toolbar">
|
||||
<div class="van-picker__cancel">取消</div>
|
||||
<!---->
|
||||
<div class="van-picker__confirm">确认</div>
|
||||
</div>
|
||||
<!---->
|
||||
<div class="van-picker__columns" style="height: 220px;">
|
||||
<div class="van-picker-column" style="height: 220px;">
|
||||
<ul style="transform: translate3d(0, 88px, 0); line-height: 44px;">
|
||||
@ -154,10 +144,8 @@ exports[`watch areaList & code 1`] = `
|
||||
<div class="van-picker van-area">
|
||||
<div class="van-hairline--top-bottom van-picker__toolbar">
|
||||
<div class="van-picker__cancel">取消</div>
|
||||
<!---->
|
||||
<div class="van-picker__confirm">确认</div>
|
||||
</div>
|
||||
<!---->
|
||||
<div class="van-picker__columns" style="height: 220px;">
|
||||
<div class="van-picker-column" style="height: 220px;">
|
||||
<ul style="transform: translate3d(0, 88px, 0); line-height: 44px;"></ul>
|
||||
@ -177,10 +165,8 @@ exports[`watch areaList & code 2`] = `
|
||||
<div class="van-picker van-area">
|
||||
<div class="van-hairline--top-bottom van-picker__toolbar">
|
||||
<div class="van-picker__cancel">取消</div>
|
||||
<!---->
|
||||
<div class="van-picker__confirm">确认</div>
|
||||
</div>
|
||||
<!---->
|
||||
<div class="van-picker__columns" style="height: 220px;">
|
||||
<div class="van-picker-column" style="height: 220px;">
|
||||
<ul style="transform: translate3d(0, 88px, 0); line-height: 44px;">
|
||||
@ -209,10 +195,8 @@ exports[`watch areaList & code 3`] = `
|
||||
<div class="van-picker van-area">
|
||||
<div class="van-hairline--top-bottom van-picker__toolbar">
|
||||
<div class="van-picker__cancel">取消</div>
|
||||
<!---->
|
||||
<div class="van-picker__confirm">确认</div>
|
||||
</div>
|
||||
<!---->
|
||||
<div class="van-picker__columns" style="height: 220px;">
|
||||
<div class="van-picker-column" style="height: 220px;">
|
||||
<ul style="transform: translate3d(0, 88px, 0); line-height: 44px;">
|
||||
|
@ -1,39 +1,10 @@
|
||||
|
||||
<template>
|
||||
<div
|
||||
:class="[b(), className]"
|
||||
:style="columnStyle"
|
||||
@touchstart="onTouchStart"
|
||||
@touchmove.prevent="onTouchMove"
|
||||
@touchend="onTouchEnd"
|
||||
@touchcancel="onTouchEnd"
|
||||
>
|
||||
<ul :style="wrapperStyle">
|
||||
<li
|
||||
v-for="(option, index) in options"
|
||||
v-html="getOptionText(option)"
|
||||
:style="optionStyle"
|
||||
class="van-ellipsis"
|
||||
:class="b('item', {
|
||||
disabled: isDisabled(option),
|
||||
selected: index === currentIndex
|
||||
})"
|
||||
@click="setIndex(index, true)"
|
||||
/>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import create from '../utils/create';
|
||||
import deepClone from '../utils/deep-clone';
|
||||
import { isObj, range } from '../utils';
|
||||
import { use, isObj, range } from '../utils';
|
||||
|
||||
const DEFAULT_DURATION = 200;
|
||||
const [sfc, bem] = use('picker-column');
|
||||
|
||||
export default create({
|
||||
name: 'picker-column',
|
||||
|
||||
export default sfc({
|
||||
props: {
|
||||
valueKey: String,
|
||||
className: String,
|
||||
@ -73,30 +44,6 @@ export default create({
|
||||
computed: {
|
||||
count() {
|
||||
return this.options.length;
|
||||
},
|
||||
|
||||
baseOffset() {
|
||||
return this.itemHeight * (this.visibleItemCount - 1) / 2;
|
||||
},
|
||||
|
||||
columnStyle() {
|
||||
return {
|
||||
height: this.itemHeight * this.visibleItemCount + 'px'
|
||||
};
|
||||
},
|
||||
|
||||
wrapperStyle() {
|
||||
return {
|
||||
transition: `${this.duration}ms`,
|
||||
transform: `translate3d(0, ${this.offset + this.baseOffset}px, 0)`,
|
||||
lineHeight: this.itemHeight + 'px'
|
||||
};
|
||||
},
|
||||
|
||||
optionStyle() {
|
||||
return {
|
||||
height: this.itemHeight + 'px'
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
@ -108,6 +55,7 @@ export default create({
|
||||
},
|
||||
|
||||
onTouchMove(event) {
|
||||
event.preventDefault();
|
||||
const deltaY = event.touches[0].clientY - this.startY;
|
||||
this.offset = range(
|
||||
this.startOffset + deltaY,
|
||||
@ -119,11 +67,7 @@ export default create({
|
||||
onTouchEnd() {
|
||||
if (this.offset !== this.startOffset) {
|
||||
this.duration = DEFAULT_DURATION;
|
||||
const index = range(
|
||||
Math.round(-this.offset / this.itemHeight),
|
||||
0,
|
||||
this.count - 1
|
||||
);
|
||||
const index = range(Math.round(-this.offset / this.itemHeight), 0, this.count - 1);
|
||||
this.setIndex(index, true);
|
||||
}
|
||||
},
|
||||
@ -143,9 +87,7 @@ export default create({
|
||||
},
|
||||
|
||||
getOptionText(option) {
|
||||
return isObj(option) && this.valueKey in option
|
||||
? option[this.valueKey]
|
||||
: option;
|
||||
return isObj(option) && this.valueKey in option ? option[this.valueKey] : option;
|
||||
},
|
||||
|
||||
setIndex(index, userAction) {
|
||||
@ -170,6 +112,55 @@ export default create({
|
||||
getValue() {
|
||||
return this.options[this.currentIndex];
|
||||
}
|
||||
},
|
||||
|
||||
render(h) {
|
||||
const { itemHeight, visibleItemCount } = this;
|
||||
|
||||
const columnStyle = {
|
||||
height: itemHeight * visibleItemCount + 'px'
|
||||
};
|
||||
|
||||
const baseOffset = (itemHeight * (visibleItemCount - 1)) / 2;
|
||||
|
||||
const wrapperStyle = {
|
||||
transition: `${this.duration}ms`,
|
||||
transform: `translate3d(0, ${this.offset + baseOffset}px, 0)`,
|
||||
lineHeight: `${itemHeight}px`
|
||||
};
|
||||
|
||||
const optionStyle = {
|
||||
height: `${itemHeight}px`
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
style={columnStyle}
|
||||
class={[bem(), this.className]}
|
||||
onTouchstart={this.onTouchStart}
|
||||
onTouchmove={this.onTouchMove}
|
||||
onTouchend={this.onTouchEnd}
|
||||
onTouchcancel={this.onTouchEnd}
|
||||
>
|
||||
<ul style={wrapperStyle}>
|
||||
{this.options.map((option, index) => (
|
||||
<li
|
||||
style={optionStyle}
|
||||
class={[
|
||||
'van-ellipsis',
|
||||
bem('item', {
|
||||
disabled: this.isDisabled(option),
|
||||
selected: index === this.currentIndex
|
||||
})
|
||||
]}
|
||||
domPropsInnerHTML={this.getOptionText(option)}
|
||||
onClick={() => {
|
||||
this.setIndex(index, true);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
</script>
|
@ -1,75 +1,14 @@
|
||||
<template>
|
||||
<div :class="b()">
|
||||
<div
|
||||
v-if="showToolbar"
|
||||
:class="b('toolbar')"
|
||||
class="van-hairline--top-bottom"
|
||||
>
|
||||
<slot>
|
||||
<div
|
||||
v-text="cancelButtonText || $t('cancel')"
|
||||
:class="b('cancel')"
|
||||
@click="emit('cancel')"
|
||||
/>
|
||||
<div
|
||||
v-if="title"
|
||||
v-text="title"
|
||||
:class="b('title')"
|
||||
class="van-ellipsis"
|
||||
/>
|
||||
<div
|
||||
v-text="confirmButtonText || $t('confirm')"
|
||||
:class="b('confirm')"
|
||||
@click="emit('confirm')"
|
||||
/>
|
||||
</slot>
|
||||
</div>
|
||||
<div
|
||||
v-if="loading"
|
||||
:class="b('loading')"
|
||||
>
|
||||
<loading />
|
||||
</div>
|
||||
<div
|
||||
:class="b('columns')"
|
||||
:style="columnsStyle"
|
||||
@touchmove.prevent
|
||||
>
|
||||
<picker-column
|
||||
v-for="(item, index) in (simple ? [columns] : columns)"
|
||||
:key="index"
|
||||
:value-key="valueKey"
|
||||
:initial-options="simple ? item : item.values"
|
||||
:class-name="item.className"
|
||||
:default-index="item.defaultIndex"
|
||||
:item-height="itemHeight"
|
||||
:visible-item-count="visibleItemCount"
|
||||
@change="onChange(index)"
|
||||
/>
|
||||
<div
|
||||
:class="b('frame')"
|
||||
class="van-hairline--top-bottom"
|
||||
:style="frameStyle"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import create from '../utils/create';
|
||||
import { use } from '../utils';
|
||||
import Loading from '../loading';
|
||||
import PickerColumn from './PickerColumn';
|
||||
import deepClone from '../utils/deep-clone';
|
||||
import PickerMixin from '../mixins/picker';
|
||||
|
||||
export default create({
|
||||
name: 'picker',
|
||||
const [sfc, bem, t] = use('picker');
|
||||
|
||||
export default sfc({
|
||||
mixins: [PickerMixin],
|
||||
|
||||
components: {
|
||||
PickerColumn
|
||||
},
|
||||
|
||||
props: {
|
||||
columns: Array,
|
||||
valueKey: {
|
||||
@ -85,18 +24,6 @@ export default create({
|
||||
},
|
||||
|
||||
computed: {
|
||||
frameStyle() {
|
||||
return {
|
||||
height: this.itemHeight + 'px'
|
||||
};
|
||||
},
|
||||
|
||||
columnsStyle() {
|
||||
return {
|
||||
height: this.itemHeight * this.visibleItemCount + 'px'
|
||||
};
|
||||
},
|
||||
|
||||
simple() {
|
||||
return this.columns.length && !this.columns[0].values;
|
||||
}
|
||||
@ -196,7 +123,74 @@ export default create({
|
||||
indexes.forEach((optionIndex, columnIndex) => {
|
||||
this.setColumnIndex(columnIndex, optionIndex);
|
||||
});
|
||||
},
|
||||
|
||||
onConfirm() {
|
||||
this.emit('confirm');
|
||||
},
|
||||
|
||||
onCancel() {
|
||||
this.emit('cancel');
|
||||
}
|
||||
},
|
||||
|
||||
render(h) {
|
||||
const { itemHeight } = this;
|
||||
const columns = this.simple ? [this.columns] : this.columns;
|
||||
|
||||
const frameStyle = {
|
||||
height: `${itemHeight}px`
|
||||
};
|
||||
|
||||
const columnsStyle = {
|
||||
height: `${itemHeight * this.visibleItemCount}px`
|
||||
};
|
||||
|
||||
const Toolbar = this.showToolbar && (
|
||||
<div class={['van-hairline--top-bottom', bem('toolbar')]}>
|
||||
{this.$slots.default || [
|
||||
<div class={bem('cancel')} onClick={this.onCancel}>
|
||||
{this.cancelButtonText || t('cancel')}
|
||||
</div>,
|
||||
this.title && <div class={['van-ellipsis', bem('title')]}>{this.title}</div>,
|
||||
<div class={bem('confirm')} onClick={this.onConfirm}>
|
||||
{this.confirmButtonText || t('confirm')}
|
||||
</div>
|
||||
]}
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div class={bem()}>
|
||||
{Toolbar}
|
||||
{this.loading && (
|
||||
<div class={bem('loading')}>
|
||||
<Loading />
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
class={bem('columns')}
|
||||
style={columnsStyle}
|
||||
onTouchmove={event => {
|
||||
event.preventDefault();
|
||||
}}
|
||||
>
|
||||
{columns.map((item, index) => (
|
||||
<PickerColumn
|
||||
valueKey={this.valueKey}
|
||||
className={item.className}
|
||||
itemHeight={this.itemHeight}
|
||||
defaultIndex={item.defaultIndex}
|
||||
visibleItemCount={this.visibleItemCount}
|
||||
initialOptions={this.simple ? item : item.values}
|
||||
onChange={() => {
|
||||
this.onChange(index);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
<div class={['van-hairline--top-bottom', bem('frame')]} style={frameStyle} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
</script>
|
@ -4,8 +4,6 @@ exports[`renders demo correctly 1`] = `
|
||||
<div>
|
||||
<div>
|
||||
<div class="van-picker">
|
||||
<!---->
|
||||
<!---->
|
||||
<div class="van-picker__columns" style="height:220px;">
|
||||
<div class="van-picker-column" style="height:220px;">
|
||||
<ul style="transition:0ms;transform:translate3d(0, 88px, 0);line-height:44px;">
|
||||
@ -22,8 +20,6 @@ exports[`renders demo correctly 1`] = `
|
||||
</div>
|
||||
<div>
|
||||
<div class="van-picker">
|
||||
<!---->
|
||||
<!---->
|
||||
<div class="van-picker__columns" style="height:220px;">
|
||||
<div class="van-picker-column" style="height:220px;">
|
||||
<ul style="transition:0ms;transform:translate3d(0, 44px, 0);line-height:44px;">
|
||||
@ -43,7 +39,6 @@ exports[`renders demo correctly 1`] = `
|
||||
<div class="van-ellipsis van-picker__title">标题</div>
|
||||
<div class="van-picker__confirm">确认</div>
|
||||
</div>
|
||||
<!---->
|
||||
<div class="van-picker__columns" style="height:220px;">
|
||||
<div class="van-picker-column" style="height:220px;">
|
||||
<ul style="transition:0ms;transform:translate3d(0, 88px, 0);line-height:44px;">
|
||||
@ -60,8 +55,6 @@ exports[`renders demo correctly 1`] = `
|
||||
</div>
|
||||
<div>
|
||||
<div class="van-picker">
|
||||
<!---->
|
||||
<!---->
|
||||
<div class="van-picker__columns" style="height:220px;">
|
||||
<div class="van-picker-column column1" style="height:220px;">
|
||||
<ul style="transition:0ms;transform:translate3d(0, 88px, 0);line-height:44px;">
|
||||
@ -84,7 +77,6 @@ exports[`renders demo correctly 1`] = `
|
||||
</div>
|
||||
<div>
|
||||
<div class="van-picker">
|
||||
<!---->
|
||||
<div class="van-picker__loading">
|
||||
<div class="van-loading van-loading--circular van-loading" style="color:#c9c9c9;width:undefined;height:undefined;"><span class="van-loading__spinner van-loading__spinner--circular"><svg viewBox="25 25 50 50" class="van-loading__circular"><circle cx="50" cy="50" r="20" fill="none"></circle></svg></span></div>
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user