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_ | - |
|
||||
| columns-placeholder `v2.2.5` | Placeholder of columns | _string[]_ | `[]` |
|
||||
| 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` |
|
||||
| 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` |
|
||||
|
@ -64,7 +64,7 @@ Vue.use(Area);
|
||||
| area-list | 省市区数据,格式见下方 | _object_ | - |
|
||||
| columns-placeholder `v2.2.5` | 列占位提示文字 | _string[]_ | `[]` |
|
||||
| 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` |
|
||||
| visible-item-count | 可见的选项个数 | _number \| string_ | `5` |
|
||||
| swipe-duration `v2.2.13` | 快速滑动时惯性滚动的时长,单位`ms` | _number \| string_ | `1000` |
|
||||
|
@ -198,7 +198,7 @@ export default {
|
||||
| loading | Whether to show loading prompt | _boolean_ | `false` |
|
||||
| filter | Option filter | _(type, vals) => vals_ | - |
|
||||
| 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` |
|
||||
| swipe-duration `v2.2.13` | Duration of the momentum animation,unit `ms` | _number \| string_ | `1000` |
|
||||
|
||||
|
@ -205,7 +205,7 @@ export default {
|
||||
| loading | 是否显示加载状态 | _boolean_ | `false` |
|
||||
| filter | 选项过滤函数 | _(type, vals) => vals_ | - |
|
||||
| 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` |
|
||||
| swipe-duration `v2.2.13` | 快速滑动时惯性滚动的时长,单位`ms` | _number \| string_ | `1000` |
|
||||
|
||||
|
@ -33,7 +33,7 @@ export default createComponent({
|
||||
valueKey: String,
|
||||
allowHtml: Boolean,
|
||||
className: String,
|
||||
itemHeight: [Number, String],
|
||||
itemHeight: Number,
|
||||
defaultIndex: Number,
|
||||
swipeDuration: [Number, String],
|
||||
visibleItemCount: [Number, String],
|
||||
|
@ -252,7 +252,7 @@ export default {
|
||||
| show-toolbar | Whether to show toolbar | _boolean_ | `false` |
|
||||
| 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` |
|
||||
| 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` |
|
||||
| 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` |
|
||||
| allow-html `v2.1.8` | 是否允许选项内容中渲染 HTML | _boolean_ | `true` |
|
||||
| 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` |
|
||||
| swipe-duration `v2.2.10` | 快速滑动时惯性滚动的时长,单位`ms` | _number \| string_ | `1000` |
|
||||
| swipe-duration `v2.2.10` | 快速滑动时惯性滚动的时长,单位 `ms` | _number \| string_ | `1000` |
|
||||
|
||||
### Events
|
||||
|
||||
|
@ -3,6 +3,7 @@ import { createNamespace, isObject } from '../utils';
|
||||
import { preventDefault } from '../utils/dom/event';
|
||||
import { BORDER_UNSET_TOP_BOTTOM } from '../utils/constant';
|
||||
import { pickerProps } from './shared';
|
||||
import { unitToPx } from '../utils/format/unit';
|
||||
|
||||
// Components
|
||||
import Loading from '../loading';
|
||||
@ -39,6 +40,10 @@ export default createComponent({
|
||||
},
|
||||
|
||||
computed: {
|
||||
itemPxHeight() {
|
||||
return unitToPx(this.itemHeight);
|
||||
},
|
||||
|
||||
dataType() {
|
||||
const { columns } = this;
|
||||
const firstColumn = columns[0] || {};
|
||||
@ -277,12 +282,38 @@ export default createComponent({
|
||||
},
|
||||
|
||||
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) => (
|
||||
<PickerColumn
|
||||
valueKey={this.valueKey}
|
||||
allowHtml={this.allowHtml}
|
||||
className={item.className}
|
||||
itemHeight={this.itemHeight}
|
||||
itemHeight={this.itemPxHeight}
|
||||
defaultIndex={item.defaultIndex || +this.defaultIndex}
|
||||
swipeDuration={this.swipeDuration}
|
||||
visibleItemCount={this.visibleItemCount}
|
||||
@ -296,38 +327,12 @@ export default createComponent({
|
||||
},
|
||||
|
||||
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 (
|
||||
<div class={bem()}>
|
||||
{this.toolbarPosition === 'top' ? this.genToolbar() : h()}
|
||||
{this.loading ? <Loading class={bem('loading')} /> : h()}
|
||||
{this.slots('columns-top')}
|
||||
<div
|
||||
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.genColumns()}
|
||||
{this.slots('columns-bottom')}
|
||||
{this.toolbarPosition === 'bottom' ? this.genToolbar() : h()}
|
||||
</div>
|
||||
|
@ -103,6 +103,27 @@ exports[`render title slot 1`] = `
|
||||
</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`] = `
|
||||
<div class="van-picker">
|
||||
<!---->
|
||||
|
@ -261,3 +261,21 @@ test('should not reset index when columns unchanged', () => {
|
||||
wrapper.find('.van-picker__confirm').trigger('click');
|
||||
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);
|
||||
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 { camelize } from '../format/string';
|
||||
import { formatNumber } from '../format/number';
|
||||
import { addUnit, unitToPx } from '../format/unit';
|
||||
|
||||
test('deepClone', () => {
|
||||
const a = { foo: 0 };
|
||||
@ -115,3 +116,27 @@ test('formatNumber', () => {
|
||||
expect(formatNumber('-1.2-', true)).toEqual('-1.2');
|
||||
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