mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
feat(Picker): item-height support rem unit (#6462)
This commit is contained in:
parent
76c9e7ef1e
commit
2f2760aba6
@ -64,7 +64,7 @@ To have a selected value,simply pass the `code` of target area to `value` prop
|
|||||||
| area-list | Area list data | _object_ | - |
|
| area-list | Area list data | _object_ | - |
|
||||||
| columns-placeholder `v2.2.5` | Placeholder of columns | _string[]_ | `[]` |
|
| columns-placeholder `v2.2.5` | Placeholder of columns | _string[]_ | `[]` |
|
||||||
| loading | Whether to show loading prompt | _boolean_ | `false` |
|
| loading | Whether to show loading prompt | _boolean_ | `false` |
|
||||||
| item-height | Option height | _number \| string_ | `44` |
|
| item-height `v2.8.6` | Option height, supports `px` ans `rem` unit, default `px` | _number \| string_ | `44` |
|
||||||
| columns-num | Level of picker | _number \| string_ | `3` |
|
| columns-num | Level of picker | _number \| string_ | `3` |
|
||||||
| visible-item-count | Count of visible columns | _number \| string_ | `5` |
|
| visible-item-count | Count of visible columns | _number \| string_ | `5` |
|
||||||
| swipe-duration `v2.2.13` | Duration of the momentum animation,unit `ms` | _number \| string_ | `1000` |
|
| swipe-duration `v2.2.13` | Duration of the momentum animation,unit `ms` | _number \| string_ | `1000` |
|
||||||
|
@ -64,7 +64,7 @@ Vue.use(Area);
|
|||||||
| area-list | 省市区数据,格式见下方 | _object_ | - |
|
| area-list | 省市区数据,格式见下方 | _object_ | - |
|
||||||
| columns-placeholder `v2.2.5` | 列占位提示文字 | _string[]_ | `[]` |
|
| columns-placeholder `v2.2.5` | 列占位提示文字 | _string[]_ | `[]` |
|
||||||
| loading | 是否显示加载状态 | _boolean_ | `false` |
|
| loading | 是否显示加载状态 | _boolean_ | `false` |
|
||||||
| item-height | 选项高度 | _number \| string_ | `44` |
|
| item-height `v2.8.6` | 选项高度,支持 `px` 和 `rem` 单位,默认 `px` | _number \| string_ | `44` |
|
||||||
| columns-num | 显示列数,3-省市区,2-省市,1-省 | _number \| string_ | `3` |
|
| columns-num | 显示列数,3-省市区,2-省市,1-省 | _number \| string_ | `3` |
|
||||||
| visible-item-count | 可见的选项个数 | _number \| string_ | `5` |
|
| visible-item-count | 可见的选项个数 | _number \| string_ | `5` |
|
||||||
| swipe-duration `v2.2.13` | 快速滑动时惯性滚动的时长,单位`ms` | _number \| string_ | `1000` |
|
| swipe-duration `v2.2.13` | 快速滑动时惯性滚动的时长,单位`ms` | _number \| string_ | `1000` |
|
||||||
|
@ -198,7 +198,7 @@ export default {
|
|||||||
| loading | Whether to show loading prompt | _boolean_ | `false` |
|
| loading | Whether to show loading prompt | _boolean_ | `false` |
|
||||||
| filter | Option filter | _(type, vals) => vals_ | - |
|
| filter | Option filter | _(type, vals) => vals_ | - |
|
||||||
| formatter | Option text formatter | _(type, val) => val_ | - |
|
| formatter | Option text formatter | _(type, val) => val_ | - |
|
||||||
| item-height | Option height | _number \| string_ | `44` |
|
| item-height `v2.8.6` | Option height, supports `px` ans `rem` unit, default `px` | _number \| string_ | `44` |
|
||||||
| visible-item-count | Count of visible columns | _number \| string_ | `5` |
|
| visible-item-count | Count of visible columns | _number \| string_ | `5` |
|
||||||
| swipe-duration `v2.2.13` | Duration of the momentum animation,unit `ms` | _number \| string_ | `1000` |
|
| swipe-duration `v2.2.13` | Duration of the momentum animation,unit `ms` | _number \| string_ | `1000` |
|
||||||
|
|
||||||
|
@ -205,7 +205,7 @@ export default {
|
|||||||
| loading | 是否显示加载状态 | _boolean_ | `false` |
|
| loading | 是否显示加载状态 | _boolean_ | `false` |
|
||||||
| filter | 选项过滤函数 | _(type, vals) => vals_ | - |
|
| filter | 选项过滤函数 | _(type, vals) => vals_ | - |
|
||||||
| formatter | 选项格式化函数 | _(type, val) => val_ | - |
|
| formatter | 选项格式化函数 | _(type, val) => val_ | - |
|
||||||
| item-height | 选项高度 | _number \| string_ | `44` |
|
| item-height `v2.8.6` | 选项高度,支持 `px` 和 `rem` 单位,默认 `px` | _number \| string_ | `44` |
|
||||||
| visible-item-count | 可见的选项个数 | _number \| string_ | `5` |
|
| visible-item-count | 可见的选项个数 | _number \| string_ | `5` |
|
||||||
| swipe-duration `v2.2.13` | 快速滑动时惯性滚动的时长,单位`ms` | _number \| string_ | `1000` |
|
| swipe-duration `v2.2.13` | 快速滑动时惯性滚动的时长,单位`ms` | _number \| string_ | `1000` |
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ export default createComponent({
|
|||||||
valueKey: String,
|
valueKey: String,
|
||||||
allowHtml: Boolean,
|
allowHtml: Boolean,
|
||||||
className: String,
|
className: String,
|
||||||
itemHeight: [Number, String],
|
itemHeight: Number,
|
||||||
defaultIndex: Number,
|
defaultIndex: Number,
|
||||||
swipeDuration: [Number, String],
|
swipeDuration: [Number, String],
|
||||||
visibleItemCount: [Number, String],
|
visibleItemCount: [Number, String],
|
||||||
|
@ -252,7 +252,7 @@ export default {
|
|||||||
| show-toolbar | Whether to show toolbar | _boolean_ | `false` |
|
| show-toolbar | Whether to show toolbar | _boolean_ | `false` |
|
||||||
| allow-html `v2.1.8` | Whether to allow HTML in option text | _boolean_ | `true` |
|
| allow-html `v2.1.8` | Whether to allow HTML in option text | _boolean_ | `true` |
|
||||||
| default-index | Default value index of single column picker | _number \| string_ | `0` |
|
| default-index | Default value index of single column picker | _number \| string_ | `0` |
|
||||||
| item-height | Option height | _number \| string_ | `44` |
|
| item-height `v2.8.6` | Option height, supports `px` ans `rem` unit, default `px` | _number \| string_ | `44` |
|
||||||
| visible-item-count | Count of visible columns | _number \| string_ | `5` |
|
| visible-item-count | Count of visible columns | _number \| string_ | `5` |
|
||||||
| swipe-duration `v2.2.10` | Duration of the momentum animation,unit `ms` | _number \| string_ | `1000` |
|
| swipe-duration `v2.2.10` | Duration of the momentum animation,unit `ms` | _number \| string_ | `1000` |
|
||||||
|
|
||||||
|
@ -275,9 +275,9 @@ export default {
|
|||||||
| show-toolbar | 是否显示顶部栏 | _boolean_ | `false` |
|
| show-toolbar | 是否显示顶部栏 | _boolean_ | `false` |
|
||||||
| allow-html `v2.1.8` | 是否允许选项内容中渲染 HTML | _boolean_ | `true` |
|
| allow-html `v2.1.8` | 是否允许选项内容中渲染 HTML | _boolean_ | `true` |
|
||||||
| default-index | 单列选择时,默认选中项的索引 | _number \| string_ | `0` |
|
| default-index | 单列选择时,默认选中项的索引 | _number \| string_ | `0` |
|
||||||
| item-height | 选项高度 | _number \| string_ | `44` |
|
| item-height `v2.8.6` | 选项高度,支持 `px` 和 `rem` 单位,默认 `px` | _number \| string_ | `44` |
|
||||||
| visible-item-count | 可见的选项个数 | _number \| string_ | `5` |
|
| visible-item-count | 可见的选项个数 | _number \| string_ | `5` |
|
||||||
| swipe-duration `v2.2.10` | 快速滑动时惯性滚动的时长,单位`ms` | _number \| string_ | `1000` |
|
| swipe-duration `v2.2.10` | 快速滑动时惯性滚动的时长,单位 `ms` | _number \| string_ | `1000` |
|
||||||
|
|
||||||
### Events
|
### Events
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ import { createNamespace, isObject } from '../utils';
|
|||||||
import { preventDefault } from '../utils/dom/event';
|
import { preventDefault } from '../utils/dom/event';
|
||||||
import { BORDER_UNSET_TOP_BOTTOM } from '../utils/constant';
|
import { BORDER_UNSET_TOP_BOTTOM } from '../utils/constant';
|
||||||
import { pickerProps } from './shared';
|
import { pickerProps } from './shared';
|
||||||
|
import { unitToPx } from '../utils/format/unit';
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import Loading from '../loading';
|
import Loading from '../loading';
|
||||||
@ -39,6 +40,10 @@ export default createComponent({
|
|||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
itemPxHeight() {
|
||||||
|
return unitToPx(this.itemHeight);
|
||||||
|
},
|
||||||
|
|
||||||
dataType() {
|
dataType() {
|
||||||
const { columns } = this;
|
const { columns } = this;
|
||||||
const firstColumn = columns[0] || {};
|
const firstColumn = columns[0] || {};
|
||||||
@ -277,12 +282,38 @@ export default createComponent({
|
|||||||
},
|
},
|
||||||
|
|
||||||
genColumns() {
|
genColumns() {
|
||||||
|
const { itemPxHeight } = this;
|
||||||
|
const wrapHeight = itemPxHeight * this.visibleItemCount;
|
||||||
|
|
||||||
|
const frameStyle = { height: `${itemPxHeight}px` };
|
||||||
|
const columnsStyle = { height: `${wrapHeight}px` };
|
||||||
|
const maskStyle = {
|
||||||
|
backgroundSize: `100% ${(wrapHeight - itemPxHeight) / 2}px`,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
class={bem('columns')}
|
||||||
|
style={columnsStyle}
|
||||||
|
onTouchmove={preventDefault}
|
||||||
|
>
|
||||||
|
{this.genColumnItems()}
|
||||||
|
<div class={bem('mask')} style={maskStyle} />
|
||||||
|
<div
|
||||||
|
class={[BORDER_UNSET_TOP_BOTTOM, bem('frame')]}
|
||||||
|
style={frameStyle}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
genColumnItems() {
|
||||||
return this.formattedColumns.map((item, columnIndex) => (
|
return this.formattedColumns.map((item, columnIndex) => (
|
||||||
<PickerColumn
|
<PickerColumn
|
||||||
valueKey={this.valueKey}
|
valueKey={this.valueKey}
|
||||||
allowHtml={this.allowHtml}
|
allowHtml={this.allowHtml}
|
||||||
className={item.className}
|
className={item.className}
|
||||||
itemHeight={this.itemHeight}
|
itemHeight={this.itemPxHeight}
|
||||||
defaultIndex={item.defaultIndex || +this.defaultIndex}
|
defaultIndex={item.defaultIndex || +this.defaultIndex}
|
||||||
swipeDuration={this.swipeDuration}
|
swipeDuration={this.swipeDuration}
|
||||||
visibleItemCount={this.visibleItemCount}
|
visibleItemCount={this.visibleItemCount}
|
||||||
@ -296,38 +327,12 @@ export default createComponent({
|
|||||||
},
|
},
|
||||||
|
|
||||||
render(h) {
|
render(h) {
|
||||||
const itemHeight = +this.itemHeight;
|
|
||||||
const wrapHeight = itemHeight * this.visibleItemCount;
|
|
||||||
|
|
||||||
const frameStyle = {
|
|
||||||
height: `${itemHeight}px`,
|
|
||||||
};
|
|
||||||
|
|
||||||
const columnsStyle = {
|
|
||||||
height: `${wrapHeight}px`,
|
|
||||||
};
|
|
||||||
|
|
||||||
const maskStyle = {
|
|
||||||
backgroundSize: `100% ${(wrapHeight - itemHeight) / 2}px`,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={bem()}>
|
<div class={bem()}>
|
||||||
{this.toolbarPosition === 'top' ? this.genToolbar() : h()}
|
{this.toolbarPosition === 'top' ? this.genToolbar() : h()}
|
||||||
{this.loading ? <Loading class={bem('loading')} /> : h()}
|
{this.loading ? <Loading class={bem('loading')} /> : h()}
|
||||||
{this.slots('columns-top')}
|
{this.slots('columns-top')}
|
||||||
<div
|
{this.genColumns()}
|
||||||
class={bem('columns')}
|
|
||||||
style={columnsStyle}
|
|
||||||
onTouchmove={preventDefault}
|
|
||||||
>
|
|
||||||
{this.genColumns()}
|
|
||||||
<div class={bem('mask')} style={maskStyle} />
|
|
||||||
<div
|
|
||||||
class={[BORDER_UNSET_TOP_BOTTOM, bem('frame')]}
|
|
||||||
style={frameStyle}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{this.slots('columns-bottom')}
|
{this.slots('columns-bottom')}
|
||||||
{this.toolbarPosition === 'bottom' ? this.genToolbar() : h()}
|
{this.toolbarPosition === 'bottom' ? this.genToolbar() : h()}
|
||||||
</div>
|
</div>
|
||||||
|
@ -103,6 +103,27 @@ exports[`render title slot 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`set rem item-height 1`] = `
|
||||||
|
<div class="van-picker">
|
||||||
|
<!---->
|
||||||
|
<div class="van-picker__columns" style="height: 800px;">
|
||||||
|
<div class="van-picker-column">
|
||||||
|
<ul class="van-picker-column__wrapper" style="transform: translate3d(0, 320px, 0); transition-duration: 0ms; transition-property: none;">
|
||||||
|
<li role="button" tabindex="0" class="van-picker-column__item van-picker-column__item--selected" style="height: 160px;">
|
||||||
|
<div class="van-ellipsis">1990</div>
|
||||||
|
</li>
|
||||||
|
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 160px;">
|
||||||
|
<div class="van-ellipsis">1991</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="van-picker__mask" style="background-size: 100% 320px;"></div>
|
||||||
|
<div class="van-hairline-unset--top-bottom van-picker__frame" style="height: 160px;"></div>
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`toolbar-position prop 1`] = `
|
exports[`toolbar-position prop 1`] = `
|
||||||
<div class="van-picker">
|
<div class="van-picker">
|
||||||
<!---->
|
<!---->
|
||||||
|
@ -261,3 +261,21 @@ test('should not reset index when columns unchanged', () => {
|
|||||||
wrapper.find('.van-picker__confirm').trigger('click');
|
wrapper.find('.van-picker__confirm').trigger('click');
|
||||||
expect(wrapper.emitted('confirm')[0]).toEqual(['2', 1]);
|
expect(wrapper.emitted('confirm')[0]).toEqual(['2', 1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('set rem item-height', async () => {
|
||||||
|
const originGetComputedStyle = window.getComputedStyle;
|
||||||
|
|
||||||
|
window.getComputedStyle = () => ({ fontSize: '16px' });
|
||||||
|
|
||||||
|
const wrapper = mount(Picker, {
|
||||||
|
propsData: {
|
||||||
|
columns: simpleColumn.slice(0, 2),
|
||||||
|
itemHeight: '10rem',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await later();
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
|
||||||
|
window.getComputedStyle = originGetComputedStyle;
|
||||||
|
});
|
||||||
|
@ -9,3 +9,24 @@ export function addUnit(value?: string | number): string | undefined {
|
|||||||
value = String(value);
|
value = String(value);
|
||||||
return isNumeric(value) ? `${value}px` : value;
|
return isNumeric(value) ? `${value}px` : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function convertRem(value: string) {
|
||||||
|
const rootStyle = window.getComputedStyle(document.documentElement);
|
||||||
|
const rootFontSize = parseFloat(rootStyle.fontSize);
|
||||||
|
|
||||||
|
value = value.replace(/rem/g, '');
|
||||||
|
|
||||||
|
return +value * rootFontSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function unitToPx(value: string | number): number {
|
||||||
|
if (typeof value === 'number') {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.indexOf('rem') !== -1) {
|
||||||
|
return convertRem(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseFloat(value);
|
||||||
|
}
|
||||||
|
@ -9,6 +9,7 @@ import { isNumeric } from '../validate/number';
|
|||||||
import { isAndroid } from '../validate/system';
|
import { isAndroid } from '../validate/system';
|
||||||
import { camelize } from '../format/string';
|
import { camelize } from '../format/string';
|
||||||
import { formatNumber } from '../format/number';
|
import { formatNumber } from '../format/number';
|
||||||
|
import { addUnit, unitToPx } from '../format/unit';
|
||||||
|
|
||||||
test('deepClone', () => {
|
test('deepClone', () => {
|
||||||
const a = { foo: 0 };
|
const a = { foo: 0 };
|
||||||
@ -115,3 +116,27 @@ test('formatNumber', () => {
|
|||||||
expect(formatNumber('-1.2-', true)).toEqual('-1.2');
|
expect(formatNumber('-1.2-', true)).toEqual('-1.2');
|
||||||
expect(formatNumber('123-')).toEqual('123');
|
expect(formatNumber('123-')).toEqual('123');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('addUnit', () => {
|
||||||
|
expect(addUnit(0)).toEqual('0px');
|
||||||
|
expect(addUnit(10)).toEqual('10px');
|
||||||
|
expect(addUnit('1%')).toEqual('1%');
|
||||||
|
expect(addUnit('1px')).toEqual('1px');
|
||||||
|
expect(addUnit('1vw')).toEqual('1vw');
|
||||||
|
expect(addUnit('1vh')).toEqual('1vh');
|
||||||
|
expect(addUnit('1rem')).toEqual('1rem');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('unitToPx', () => {
|
||||||
|
const originGetComputedStyle = window.getComputedStyle;
|
||||||
|
|
||||||
|
window.getComputedStyle = () => ({ fontSize: '16px' });
|
||||||
|
|
||||||
|
expect(unitToPx(0)).toEqual(0);
|
||||||
|
expect(unitToPx(10)).toEqual(10);
|
||||||
|
expect(unitToPx('10px')).toEqual(10);
|
||||||
|
expect(unitToPx('0rem')).toEqual(0);
|
||||||
|
expect(unitToPx('10rem')).toEqual(160);
|
||||||
|
|
||||||
|
window.getComputedStyle = originGetComputedStyle;
|
||||||
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user