mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-23 18:00:27 +08:00
chore(Slider): use tsx
This commit is contained in:
parent
6341967482
commit
f879b6d77a
@ -1,13 +1,13 @@
|
|||||||
import { ref, computed } from 'vue';
|
import { ref, computed, PropType, CSSProperties } from 'vue';
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
import {
|
import {
|
||||||
addUnit,
|
addUnit,
|
||||||
getSizeStyle,
|
getSizeStyle,
|
||||||
preventDefault,
|
preventDefault,
|
||||||
|
stopPropagation,
|
||||||
createNamespace,
|
createNamespace,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import { deepClone } from '../utils/deep-clone';
|
|
||||||
|
|
||||||
// Composition
|
// Composition
|
||||||
import { useRect } from '@vant/use';
|
import { useRect } from '@vant/use';
|
||||||
@ -16,6 +16,8 @@ import { useLinkField } from '../composition/use-link-field';
|
|||||||
|
|
||||||
const [createComponent, bem] = createNamespace('slider');
|
const [createComponent, bem] = createNamespace('slider');
|
||||||
|
|
||||||
|
type SliderValue = number | number[];
|
||||||
|
|
||||||
export default createComponent({
|
export default createComponent({
|
||||||
props: {
|
props: {
|
||||||
range: Boolean,
|
range: Boolean,
|
||||||
@ -38,7 +40,7 @@ export default createComponent({
|
|||||||
default: 1,
|
default: 1,
|
||||||
},
|
},
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: [Number, Array],
|
type: [Number, Array] as PropType<SliderValue>,
|
||||||
default: 0,
|
default: 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -46,15 +48,15 @@ export default createComponent({
|
|||||||
emits: ['change', 'drag-end', 'drag-start', 'update:modelValue'],
|
emits: ['change', 'drag-end', 'drag-start', 'update:modelValue'],
|
||||||
|
|
||||||
setup(props, { emit, slots }) {
|
setup(props, { emit, slots }) {
|
||||||
let startValue;
|
let buttonIndex: number;
|
||||||
let buttonIndex;
|
let startValue: SliderValue;
|
||||||
let currentValue;
|
let currentValue: SliderValue;
|
||||||
|
|
||||||
const root = ref();
|
const root = ref<HTMLElement>();
|
||||||
const dragStatus = ref();
|
const dragStatus = ref<'start' | 'draging' | ''>();
|
||||||
const touch = useTouch();
|
const touch = useTouch();
|
||||||
|
|
||||||
const scope = computed(() => props.max - props.min);
|
const scope = computed(() => Number(props.max) - Number(props.min));
|
||||||
|
|
||||||
const wrapperStyle = computed(() => {
|
const wrapperStyle = computed(() => {
|
||||||
const crossAxis = props.vertical ? 'width' : 'height';
|
const crossAxis = props.vertical ? 'width' : 'height';
|
||||||
@ -64,56 +66,57 @@ export default createComponent({
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const isRange = (val: unknown): val is number[] =>
|
||||||
|
!!props.range && Array.isArray(val);
|
||||||
|
|
||||||
// 计算选中条的长度百分比
|
// 计算选中条的长度百分比
|
||||||
const calcMainAxis = () => {
|
const calcMainAxis = () => {
|
||||||
const { modelValue, min, range } = props;
|
const { modelValue, min } = props;
|
||||||
if (range) {
|
if (isRange(modelValue)) {
|
||||||
return `${((modelValue[1] - modelValue[0]) * 100) / scope.value}%`;
|
return `${((modelValue[1] - modelValue[0]) * 100) / scope.value}%`;
|
||||||
}
|
}
|
||||||
return `${((modelValue - min) * 100) / scope.value}%`;
|
return `${((modelValue - Number(min)) * 100) / scope.value}%`;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 计算选中条的开始位置的偏移量
|
// 计算选中条的开始位置的偏移量
|
||||||
const calcOffset = () => {
|
const calcOffset = () => {
|
||||||
const { modelValue, min, range } = props;
|
const { modelValue, min } = props;
|
||||||
if (range) {
|
if (isRange(modelValue)) {
|
||||||
return `${((modelValue[0] - min) * 100) / scope.value}%`;
|
return `${((modelValue[0] - Number(min)) * 100) / scope.value}%`;
|
||||||
}
|
}
|
||||||
return `0%`;
|
return `0%`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const barStyle = computed(() => {
|
const barStyle = computed<CSSProperties>(() => {
|
||||||
const mainAxis = props.vertical ? 'height' : 'width';
|
const mainAxis = props.vertical ? 'height' : 'width';
|
||||||
return {
|
return {
|
||||||
[mainAxis]: calcMainAxis(),
|
[mainAxis]: calcMainAxis(),
|
||||||
left: props.vertical ? null : calcOffset(),
|
left: props.vertical ? undefined : calcOffset(),
|
||||||
top: props.vertical ? calcOffset() : null,
|
top: props.vertical ? calcOffset() : undefined,
|
||||||
background: props.activeColor,
|
background: props.activeColor,
|
||||||
transition: dragStatus.value ? 'none' : null,
|
transition: dragStatus.value ? 'none' : undefined,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const format = (value) => {
|
const format = (value: number) => {
|
||||||
const { min, max, step } = props;
|
const { min, max, step } = props;
|
||||||
value = Math.max(min, Math.min(value, max));
|
value = Math.max(+min, Math.min(value, +max));
|
||||||
return Math.round(value / step) * step;
|
return Math.round(value / +step) * +step;
|
||||||
};
|
};
|
||||||
|
|
||||||
const isSameValue = (newValue, oldValue) => {
|
const isSameValue = (newValue: SliderValue, oldValue: SliderValue) =>
|
||||||
return JSON.stringify(newValue) === JSON.stringify(oldValue);
|
JSON.stringify(newValue) === JSON.stringify(oldValue);
|
||||||
};
|
|
||||||
|
|
||||||
// 处理两个滑块重叠之后的情况
|
// 处理两个滑块重叠之后的情况
|
||||||
const handleOverlap = (value) => {
|
const handleOverlap = (value: number[]) => {
|
||||||
if (value[0] > value[1]) {
|
if (value[0] > value[1]) {
|
||||||
value = deepClone(value);
|
return value.slice(0).reverse();
|
||||||
return value.reverse();
|
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateValue = (value, end) => {
|
const updateValue = (value: SliderValue, end?: boolean) => {
|
||||||
if (props.range) {
|
if (isRange(value)) {
|
||||||
value = handleOverlap(value).map(format);
|
value = handleOverlap(value).map(format);
|
||||||
} else {
|
} else {
|
||||||
value = format(value);
|
value = format(value);
|
||||||
@ -128,52 +131,53 @@ export default createComponent({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onClick = (event) => {
|
const onClick = (event: MouseEvent) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
if (props.disabled) {
|
if (props.disabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { min, vertical, modelValue, range } = props;
|
const { min, vertical, modelValue } = props;
|
||||||
const rect = useRect(root);
|
const rect = useRect(root);
|
||||||
const delta = vertical
|
const delta = vertical
|
||||||
? event.clientY - rect.top
|
? event.clientY - rect.top
|
||||||
: event.clientX - rect.left;
|
: event.clientX - rect.left;
|
||||||
const total = vertical ? rect.height : rect.width;
|
const total = vertical ? rect.height : rect.width;
|
||||||
let value = +min + (delta / total) * scope.value;
|
const value = Number(min) + (delta / total) * scope.value;
|
||||||
|
|
||||||
if (range) {
|
if (isRange(modelValue)) {
|
||||||
let left = modelValue[0];
|
const [left, right] = modelValue;
|
||||||
let right = modelValue[1];
|
|
||||||
const middle = (left + right) / 2;
|
const middle = (left + right) / 2;
|
||||||
if (value <= middle) {
|
|
||||||
left = value;
|
|
||||||
} else {
|
|
||||||
right = value;
|
|
||||||
}
|
|
||||||
value = [left, right];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (value <= middle) {
|
||||||
|
updateValue([value, right], true);
|
||||||
|
} else {
|
||||||
|
updateValue([left, value], true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
updateValue(value, true);
|
updateValue(value, true);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onTouchStart = (event) => {
|
const onTouchStart = (event: TouchEvent) => {
|
||||||
if (props.disabled) {
|
if (props.disabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
touch.start(event);
|
touch.start(event);
|
||||||
currentValue = props.modelValue;
|
currentValue = props.modelValue;
|
||||||
if (props.range) {
|
|
||||||
startValue = props.modelValue.map(format);
|
if (isRange(currentValue)) {
|
||||||
|
startValue = currentValue.map(format);
|
||||||
} else {
|
} else {
|
||||||
startValue = format(props.modelValue);
|
startValue = format(currentValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
dragStatus.value = 'start';
|
dragStatus.value = 'start';
|
||||||
};
|
};
|
||||||
|
|
||||||
const onTouchMove = (event) => {
|
const onTouchMove = (event: TouchEvent) => {
|
||||||
if (props.disabled) {
|
if (props.disabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -191,8 +195,9 @@ export default createComponent({
|
|||||||
const total = props.vertical ? rect.height : rect.width;
|
const total = props.vertical ? rect.height : rect.width;
|
||||||
const diff = (delta / total) * scope.value;
|
const diff = (delta / total) * scope.value;
|
||||||
|
|
||||||
if (props.range) {
|
if (isRange(startValue)) {
|
||||||
currentValue[buttonIndex] = startValue[buttonIndex] + diff;
|
(currentValue as number[])[buttonIndex] =
|
||||||
|
startValue[buttonIndex] + diff;
|
||||||
} else {
|
} else {
|
||||||
currentValue = startValue + diff;
|
currentValue = startValue + diff;
|
||||||
}
|
}
|
||||||
@ -212,7 +217,7 @@ export default createComponent({
|
|||||||
dragStatus.value = '';
|
dragStatus.value = '';
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderButton = (index) => {
|
const renderButton = (index?: number) => {
|
||||||
const getClassName = () => {
|
const getClassName = () => {
|
||||||
if (typeof index === 'number') {
|
if (typeof index === 'number') {
|
||||||
const position = ['left', 'right'];
|
const position = ['left', 'right'];
|
||||||
@ -221,18 +226,23 @@ export default createComponent({
|
|||||||
return `button-wrapper`;
|
return `button-wrapper`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const currentValue =
|
||||||
|
typeof index === 'number'
|
||||||
|
? (props.modelValue as number[])[index]
|
||||||
|
: (props.modelValue as number);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
role="slider"
|
role="slider"
|
||||||
class={bem(getClassName())}
|
class={bem(getClassName())}
|
||||||
tabindex={props.disabled ? -1 : 0}
|
tabindex={props.disabled ? -1 : 0}
|
||||||
aria-valuemin={props.min}
|
aria-valuemin={+props.min}
|
||||||
aria-valuenow={props.modelValue}
|
aria-valuenow={currentValue}
|
||||||
aria-valuemax={props.max}
|
aria-valuemax={+props.max}
|
||||||
aria-orientation={props.vertical ? 'vertical' : 'horizontal'}
|
aria-orientation={props.vertical ? 'vertical' : 'horizontal'}
|
||||||
onTouchstart={(e) => {
|
onTouchstart={(e) => {
|
||||||
if (typeof index === 'number') {
|
if (typeof index === 'number') {
|
||||||
// 保存当前按钮的索引
|
// save index of current button
|
||||||
buttonIndex = index;
|
buttonIndex = index;
|
||||||
}
|
}
|
||||||
onTouchStart(e);
|
onTouchStart(e);
|
||||||
@ -240,7 +250,7 @@ export default createComponent({
|
|||||||
onTouchmove={onTouchMove}
|
onTouchmove={onTouchMove}
|
||||||
onTouchend={onTouchEnd}
|
onTouchend={onTouchEnd}
|
||||||
onTouchcancel={onTouchEnd}
|
onTouchcancel={onTouchEnd}
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={stopPropagation}
|
||||||
>
|
>
|
||||||
{slots.button ? (
|
{slots.button ? (
|
||||||
slots.button()
|
slots.button()
|
Loading…
x
Reference in New Issue
Block a user