mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
Merge branch 'dev' into next
This commit is contained in:
commit
cf5e7e6629
@ -30,7 +30,7 @@
|
|||||||
</script>
|
</script>
|
||||||
<% } %>
|
<% } %>
|
||||||
</head>
|
</head>
|
||||||
<body ontouchstart>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script type="module" src="/desktop/main.js"></script>
|
<script type="module" src="/desktop/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
</script>
|
</script>
|
||||||
<% } %>
|
<% } %>
|
||||||
</head>
|
</head>
|
||||||
<body ontouchstart>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script type="module" src="/mobile/main.js"></script>
|
<script type="module" src="/mobile/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
@ -13,3 +13,8 @@ window.app = createApp(App)
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.app.mount('#app');
|
window.app.mount('#app');
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
|
// https://stackoverflow.com/questions/3885018/active-pseudo-class-doesnt-work-in-mobile-safari/33681490#33681490
|
||||||
|
document.addEventListener('touchstart', () => {}, {
|
||||||
|
passive: true,
|
||||||
|
});
|
||||||
|
@ -212,3 +212,24 @@ import 'vant/es/image-preview/style';
|
|||||||
```
|
```
|
||||||
|
|
||||||
> Tip: "Full Import" and "On-demand Import" should not be used at the same time, otherwise it will lead to problems such as code duplication and style overrides.
|
> Tip: "Full Import" and "On-demand Import" should not be used at the same time, otherwise it will lead to problems such as code duplication and style overrides.
|
||||||
|
|
||||||
|
## With Frameworks
|
||||||
|
|
||||||
|
### Use Vant in Nuxt 3
|
||||||
|
|
||||||
|
When using Vant in Nuxt 3, you should add `/vant/` to the `build.transpile`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineNuxtConfig } from 'nuxt';
|
||||||
|
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
experimental: {
|
||||||
|
externalVue: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Reference:
|
||||||
|
|
||||||
|
- [nuxt/framework#6761](https://github.com/nuxt/framework/issues/6761)
|
||||||
|
- [nuxt/framework#4084](https://github.com/nuxt/framework/issues/4084)
|
||||||
|
@ -217,3 +217,24 @@ import 'vant/es/image-preview/style';
|
|||||||
```
|
```
|
||||||
|
|
||||||
> 提示:在单个项目中不应该同时使用「全量引入」和「按需引入」,否则会导致代码重复、样式错乱等问题。
|
> 提示:在单个项目中不应该同时使用「全量引入」和「按需引入」,否则会导致代码重复、样式错乱等问题。
|
||||||
|
|
||||||
|
## 在框架中使用
|
||||||
|
|
||||||
|
### 在 Nuxt 3 中使用
|
||||||
|
|
||||||
|
在 Nuxt 3 中使用 Vant 时,由于 Nuxt 3 框架本身的限制,需要在 `nuxt.config.ts` 中添加以下配置:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineNuxtConfig } from 'nuxt';
|
||||||
|
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
experimental: {
|
||||||
|
externalVue: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
关于该问题的背景,可以参考以下 issue:
|
||||||
|
|
||||||
|
- [nuxt/framework#6761](https://github.com/nuxt/framework/issues/6761)
|
||||||
|
- [nuxt/framework#4084](https://github.com/nuxt/framework/issues/4084)
|
||||||
|
@ -134,7 +134,7 @@ export default defineComponent({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getInitialDate = (defaultDate = props.defaultDate) => {
|
const getInitialDate = (defaultDate = props.defaultDate) => {
|
||||||
const { type, minDate, maxDate } = props;
|
const { type, minDate, maxDate, allowSameDay } = props;
|
||||||
|
|
||||||
if (defaultDate === null) {
|
if (defaultDate === null) {
|
||||||
return defaultDate;
|
return defaultDate;
|
||||||
@ -149,9 +149,12 @@ export default defineComponent({
|
|||||||
const start = limitDateRange(
|
const start = limitDateRange(
|
||||||
defaultDate[0] || now,
|
defaultDate[0] || now,
|
||||||
minDate,
|
minDate,
|
||||||
getPrevDay(maxDate)
|
allowSameDay ? maxDate : getPrevDay(maxDate)
|
||||||
|
);
|
||||||
|
const end = limitDateRange(
|
||||||
|
defaultDate[1] || now,
|
||||||
|
allowSameDay ? minDate : getNextDay(minDate)
|
||||||
);
|
);
|
||||||
const end = limitDateRange(defaultDate[1] || now, getNextDay(minDate));
|
|
||||||
return [start, end];
|
return [start, end];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,3 +270,41 @@ test('should emit overRange when exceeded max range', async () => {
|
|||||||
|
|
||||||
expect(onOverRange).toHaveBeenCalledTimes(1);
|
expect(onOverRange).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should allow default date to be minDate when using allowSameDay prop', () => {
|
||||||
|
const minDate = new Date(1800, 0, 1);
|
||||||
|
const maxDate = new Date(1800, 0, 29);
|
||||||
|
const wrapper = mount(Calendar, {
|
||||||
|
props: {
|
||||||
|
type: 'range',
|
||||||
|
poppable: false,
|
||||||
|
minDate,
|
||||||
|
maxDate,
|
||||||
|
defaultDate: [minDate, minDate],
|
||||||
|
lazyRender: false,
|
||||||
|
allowSameDay: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapper.find('.van-calendar__confirm').trigger('click');
|
||||||
|
expect(wrapper.emitted<[Date]>('confirm')![0][0]).toEqual([minDate, minDate]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should allow default date to be maxDate when using allowSameDay prop', () => {
|
||||||
|
const minDate = new Date(1800, 0, 1);
|
||||||
|
const maxDate = new Date(1800, 0, 29);
|
||||||
|
const wrapper = mount(Calendar, {
|
||||||
|
props: {
|
||||||
|
type: 'range',
|
||||||
|
poppable: false,
|
||||||
|
minDate,
|
||||||
|
maxDate,
|
||||||
|
defaultDate: [maxDate, maxDate],
|
||||||
|
lazyRender: false,
|
||||||
|
allowSameDay: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapper.find('.van-calendar__confirm').trigger('click');
|
||||||
|
expect(wrapper.emitted<[Date]>('confirm')![0][0]).toEqual([maxDate, maxDate]);
|
||||||
|
});
|
||||||
|
@ -26,6 +26,7 @@ import {
|
|||||||
makeStringProp,
|
makeStringProp,
|
||||||
makeNumericProp,
|
makeNumericProp,
|
||||||
createNamespace,
|
createNamespace,
|
||||||
|
type ComponentInstance,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import {
|
import {
|
||||||
cutString,
|
cutString,
|
||||||
@ -42,7 +43,11 @@ import {
|
|||||||
import { cellSharedProps } from '../cell/Cell';
|
import { cellSharedProps } from '../cell/Cell';
|
||||||
|
|
||||||
// Composables
|
// Composables
|
||||||
import { CUSTOM_FIELD_INJECTION_KEY, useParent } from '@vant/use';
|
import {
|
||||||
|
useParent,
|
||||||
|
useEventListener,
|
||||||
|
CUSTOM_FIELD_INJECTION_KEY,
|
||||||
|
} from '@vant/use';
|
||||||
import { useId } from '../composables/use-id';
|
import { useId } from '../composables/use-id';
|
||||||
import { useExpose } from '../composables/use-expose';
|
import { useExpose } from '../composables/use-expose';
|
||||||
|
|
||||||
@ -145,6 +150,7 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const inputRef = ref<HTMLInputElement>();
|
const inputRef = ref<HTMLInputElement>();
|
||||||
|
const clearIconRef = ref<ComponentInstance>();
|
||||||
const customValue = ref<() => unknown>();
|
const customValue = ref<() => unknown>();
|
||||||
|
|
||||||
const { parent: form } = useParent(FORM_KEY);
|
const { parent: form } = useParent(FORM_KEY);
|
||||||
@ -353,7 +359,7 @@ export default defineComponent({
|
|||||||
const onClickRightIcon = (event: MouseEvent) =>
|
const onClickRightIcon = (event: MouseEvent) =>
|
||||||
emit('clickRightIcon', event);
|
emit('clickRightIcon', event);
|
||||||
|
|
||||||
const onClear = (event: MouseEvent) => {
|
const onClear = (event: TouchEvent) => {
|
||||||
preventDefault(event);
|
preventDefault(event);
|
||||||
emit('update:modelValue', '');
|
emit('update:modelValue', '');
|
||||||
emit('clear', event);
|
emit('clear', event);
|
||||||
@ -526,9 +532,9 @@ export default defineComponent({
|
|||||||
{renderInput()}
|
{renderInput()}
|
||||||
{showClear.value && (
|
{showClear.value && (
|
||||||
<Icon
|
<Icon
|
||||||
|
ref={clearIconRef}
|
||||||
name={props.clearIcon}
|
name={props.clearIcon}
|
||||||
class={bem('clear')}
|
class={bem('clear')}
|
||||||
onTouchstart={onClear}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{renderRightIcon()}
|
{renderRightIcon()}
|
||||||
@ -568,6 +574,11 @@ export default defineComponent({
|
|||||||
nextTick(adjustTextareaSize);
|
nextTick(adjustTextareaSize);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// useEventListener will set passive to `false` to eliminate the warning of Chrome
|
||||||
|
useEventListener('touchstart', onClear, {
|
||||||
|
target: computed(() => clearIconRef.value?.$el),
|
||||||
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const disabled = getProp('disabled');
|
const disabled = getProp('disabled');
|
||||||
const labelAlign = getProp('labelAlign');
|
const labelAlign = getProp('labelAlign');
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import VanField from '..';
|
import VanField from '..';
|
||||||
|
import VanForm from '../../form';
|
||||||
import VanCellGroup from '../../cell-group';
|
import VanCellGroup from '../../cell-group';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useTranslate } from '../../../docs/site';
|
import { useTranslate } from '../../../docs/site';
|
||||||
@ -43,10 +44,12 @@ const password = ref('');
|
|||||||
<template>
|
<template>
|
||||||
<demo-block :title="t('customType')">
|
<demo-block :title="t('customType')">
|
||||||
<van-cell-group inset>
|
<van-cell-group inset>
|
||||||
|
<van-form>
|
||||||
<van-field
|
<van-field
|
||||||
v-model="text"
|
v-model="text"
|
||||||
:label="t('text')"
|
:label="t('text')"
|
||||||
:placeholder="t('textPlaceholder')"
|
:placeholder="t('textPlaceholder')"
|
||||||
|
autocomplete="off"
|
||||||
/>
|
/>
|
||||||
<van-field
|
<van-field
|
||||||
v-model="phone"
|
v-model="phone"
|
||||||
@ -71,7 +74,9 @@ const password = ref('');
|
|||||||
type="password"
|
type="password"
|
||||||
:label="t('password')"
|
:label="t('password')"
|
||||||
:placeholder="t('passwordPlaceholder')"
|
:placeholder="t('passwordPlaceholder')"
|
||||||
|
autocomplete="off"
|
||||||
/>
|
/>
|
||||||
|
</van-form>
|
||||||
</van-cell-group>
|
</van-cell-group>
|
||||||
</demo-block>
|
</demo-block>
|
||||||
</template>
|
</template>
|
||||||
|
@ -26,6 +26,7 @@ exports[`should render demo and match snapshot 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="van-cell-group van-cell-group--inset">
|
<div class="van-cell-group van-cell-group--inset">
|
||||||
|
<form class="van-form">
|
||||||
<div class="van-cell van-field">
|
<div class="van-cell van-field">
|
||||||
<div class="van-cell__title van-field__label">
|
<div class="van-cell__title van-field__label">
|
||||||
<label id="van-field-label"
|
<label id="van-field-label"
|
||||||
@ -40,6 +41,7 @@ exports[`should render demo and match snapshot 1`] = `
|
|||||||
id="van-field-input"
|
id="van-field-input"
|
||||||
class="van-field__control"
|
class="van-field__control"
|
||||||
placeholder="Text"
|
placeholder="Text"
|
||||||
|
autocomplete="off"
|
||||||
aria-labelledby="van-field-label"
|
aria-labelledby="van-field-label"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
@ -118,11 +120,13 @@ exports[`should render demo and match snapshot 1`] = `
|
|||||||
id="van-field-input"
|
id="van-field-input"
|
||||||
class="van-field__control"
|
class="van-field__control"
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
|
autocomplete="off"
|
||||||
aria-labelledby="van-field-label"
|
aria-labelledby="van-field-label"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
ref,
|
||||||
watch,
|
watch,
|
||||||
computed,
|
computed,
|
||||||
reactive,
|
reactive,
|
||||||
@ -13,10 +14,12 @@ import {
|
|||||||
preventDefault,
|
preventDefault,
|
||||||
createNamespace,
|
createNamespace,
|
||||||
makeRequiredProp,
|
makeRequiredProp,
|
||||||
|
type ComponentInstance,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
|
|
||||||
// Composables
|
// Composables
|
||||||
import { useTouch } from '../composables/use-touch';
|
import { useTouch } from '../composables/use-touch';
|
||||||
|
import { useEventListener } from '@vant/use';
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import { Image } from '../image';
|
import { Image } from '../image';
|
||||||
@ -57,6 +60,7 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const touch = useTouch();
|
const touch = useTouch();
|
||||||
|
const swipeItem = ref<ComponentInstance>();
|
||||||
|
|
||||||
const vertical = computed(() => {
|
const vertical = computed(() => {
|
||||||
const { rootWidth, rootHeight } = props;
|
const { rootWidth, rootHeight } = props;
|
||||||
@ -271,6 +275,11 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// useEventListener will set passive to `false` to eliminate the warning of Chrome
|
||||||
|
useEventListener('touchmove', onTouchMove, {
|
||||||
|
target: computed(() => swipeItem.value?.$el),
|
||||||
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const imageSlots = {
|
const imageSlots = {
|
||||||
loading: () => <Loading type="spinner" />,
|
loading: () => <Loading type="spinner" />,
|
||||||
@ -278,9 +287,9 @@ export default defineComponent({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<SwipeItem
|
<SwipeItem
|
||||||
|
ref={swipeItem}
|
||||||
class={bem('swipe-item')}
|
class={bem('swipe-item')}
|
||||||
onTouchstartPassive={onTouchStart}
|
onTouchstartPassive={onTouchStart}
|
||||||
onTouchmove={onTouchMove}
|
|
||||||
onTouchend={onTouchEnd}
|
onTouchend={onTouchEnd}
|
||||||
onTouchcancel={onTouchEnd}
|
onTouchcancel={onTouchEnd}
|
||||||
>
|
>
|
||||||
|
@ -77,6 +77,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
setup(props, { emit, slots }) {
|
setup(props, { emit, slots }) {
|
||||||
const root = ref<HTMLElement>();
|
const root = ref<HTMLElement>();
|
||||||
|
const sidebar = ref<HTMLElement>();
|
||||||
const activeAnchor = ref<Numeric>('');
|
const activeAnchor = ref<Numeric>('');
|
||||||
|
|
||||||
const touch = useTouch();
|
const touch = useTouch();
|
||||||
@ -272,11 +273,11 @@ export default defineComponent({
|
|||||||
|
|
||||||
const renderSidebar = () => (
|
const renderSidebar = () => (
|
||||||
<div
|
<div
|
||||||
|
ref={sidebar}
|
||||||
class={bem('sidebar')}
|
class={bem('sidebar')}
|
||||||
style={sidebarStyle.value}
|
style={sidebarStyle.value}
|
||||||
onClick={onClickSidebar}
|
onClick={onClickSidebar}
|
||||||
onTouchstartPassive={touch.start}
|
onTouchstartPassive={touch.start}
|
||||||
onTouchmove={onTouchMove}
|
|
||||||
>
|
>
|
||||||
{renderIndexes()}
|
{renderIndexes()}
|
||||||
</div>
|
</div>
|
||||||
@ -284,6 +285,11 @@ export default defineComponent({
|
|||||||
|
|
||||||
useExpose({ scrollTo });
|
useExpose({ scrollTo });
|
||||||
|
|
||||||
|
// useEventListener will set passive to `false` to eliminate the warning of Chrome
|
||||||
|
useEventListener('touchmove', onTouchMove, {
|
||||||
|
target: sidebar,
|
||||||
|
});
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<div ref={root} class={bem()}>
|
<div ref={root} class={bem()}>
|
||||||
{props.teleport ? (
|
{props.teleport ? (
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
import {
|
import {
|
||||||
|
ref,
|
||||||
Transition,
|
Transition,
|
||||||
defineComponent,
|
defineComponent,
|
||||||
type PropType,
|
type PropType,
|
||||||
type CSSProperties,
|
type CSSProperties,
|
||||||
type ExtractPropTypes,
|
type ExtractPropTypes,
|
||||||
} from 'vue';
|
} from 'vue';
|
||||||
|
|
||||||
|
// Utils
|
||||||
import {
|
import {
|
||||||
noop,
|
|
||||||
isDef,
|
isDef,
|
||||||
extend,
|
extend,
|
||||||
truthProp,
|
truthProp,
|
||||||
@ -16,6 +18,9 @@ import {
|
|||||||
createNamespace,
|
createNamespace,
|
||||||
getZIndexStyle,
|
getZIndexStyle,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
|
|
||||||
|
// Composables
|
||||||
|
import { useEventListener } from '@vant/use';
|
||||||
import { useLazyRender } from '../composables/use-lazy-render';
|
import { useLazyRender } from '../composables/use-lazy-render';
|
||||||
|
|
||||||
const [name, bem] = createNamespace('overlay');
|
const [name, bem] = createNamespace('overlay');
|
||||||
@ -38,10 +43,13 @@ export default defineComponent({
|
|||||||
props: overlayProps,
|
props: overlayProps,
|
||||||
|
|
||||||
setup(props, { slots }) {
|
setup(props, { slots }) {
|
||||||
|
const root = ref<HTMLElement>();
|
||||||
const lazyRender = useLazyRender(() => props.show || !props.lazyRender);
|
const lazyRender = useLazyRender(() => props.show || !props.lazyRender);
|
||||||
|
|
||||||
const preventTouchMove = (event: TouchEvent) => {
|
const onTouchMove = (event: TouchEvent) => {
|
||||||
|
if (props.lockScroll) {
|
||||||
preventDefault(event, true);
|
preventDefault(event, true);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderOverlay = lazyRender(() => {
|
const renderOverlay = lazyRender(() => {
|
||||||
@ -57,15 +65,20 @@ export default defineComponent({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
v-show={props.show}
|
v-show={props.show}
|
||||||
|
ref={root}
|
||||||
style={style}
|
style={style}
|
||||||
class={[bem(), props.className]}
|
class={[bem(), props.className]}
|
||||||
onTouchmove={props.lockScroll ? preventTouchMove : noop}
|
|
||||||
>
|
>
|
||||||
{slots.default?.()}
|
{slots.default?.()}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// useEventListener will set passive to `false` to eliminate the warning of Chrome
|
||||||
|
useEventListener('touchmove', onTouchMove, {
|
||||||
|
target: root,
|
||||||
|
});
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<Transition v-slots={{ default: renderOverlay }} name="van-fade" appear />
|
<Transition v-slots={{ default: renderOverlay }} name="van-fade" appear />
|
||||||
);
|
);
|
||||||
|
@ -13,7 +13,7 @@ import {
|
|||||||
} from '../utils';
|
} from '../utils';
|
||||||
|
|
||||||
// Composables
|
// Composables
|
||||||
import { useRect, useCustomFieldValue } from '@vant/use';
|
import { useRect, useCustomFieldValue, useEventListener } from '@vant/use';
|
||||||
import { useRefs } from '../composables/use-refs';
|
import { useRefs } from '../composables/use-refs';
|
||||||
import { useTouch } from '../composables/use-touch';
|
import { useTouch } from '../composables/use-touch';
|
||||||
|
|
||||||
@ -268,6 +268,11 @@ export default defineComponent({
|
|||||||
|
|
||||||
useCustomFieldValue(() => props.modelValue);
|
useCustomFieldValue(() => props.modelValue);
|
||||||
|
|
||||||
|
// useEventListener will set passive to `false` to eliminate the warning of Chrome
|
||||||
|
useEventListener('touchmove', onTouchMove, {
|
||||||
|
target: groupRef,
|
||||||
|
});
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<div
|
<div
|
||||||
ref={groupRef}
|
ref={groupRef}
|
||||||
@ -280,7 +285,6 @@ export default defineComponent({
|
|||||||
aria-disabled={props.disabled}
|
aria-disabled={props.disabled}
|
||||||
aria-readonly={props.readonly}
|
aria-readonly={props.readonly}
|
||||||
onTouchstartPassive={onTouchStart}
|
onTouchstartPassive={onTouchStart}
|
||||||
onTouchmove={onTouchMove}
|
|
||||||
>
|
>
|
||||||
{list.value.map(renderStar)}
|
{list.value.map(renderStar)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -22,7 +22,7 @@ import {
|
|||||||
} from '../utils';
|
} from '../utils';
|
||||||
|
|
||||||
// Composables
|
// Composables
|
||||||
import { useRect, useCustomFieldValue } from '@vant/use';
|
import { useRect, useCustomFieldValue, useEventListener } from '@vant/use';
|
||||||
import { useTouch } from '../composables/use-touch';
|
import { useTouch } from '../composables/use-touch';
|
||||||
|
|
||||||
const [name, bem] = createNamespace('slider');
|
const [name, bem] = createNamespace('slider');
|
||||||
@ -65,6 +65,7 @@ export default defineComponent({
|
|||||||
let startValue: SliderValue;
|
let startValue: SliderValue;
|
||||||
|
|
||||||
const root = ref<HTMLElement>();
|
const root = ref<HTMLElement>();
|
||||||
|
const slider = ref<HTMLElement>();
|
||||||
const dragStatus = ref<'start' | 'dragging' | ''>();
|
const dragStatus = ref<'start' | 'dragging' | ''>();
|
||||||
const touch = useTouch();
|
const touch = useTouch();
|
||||||
|
|
||||||
@ -290,6 +291,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
ref={slider}
|
||||||
role="slider"
|
role="slider"
|
||||||
class={getButtonClassName(index)}
|
class={getButtonClassName(index)}
|
||||||
tabindex={props.disabled ? undefined : 0}
|
tabindex={props.disabled ? undefined : 0}
|
||||||
@ -306,7 +308,6 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
onTouchStart(event);
|
onTouchStart(event);
|
||||||
}}
|
}}
|
||||||
onTouchmove={onTouchMove}
|
|
||||||
onTouchend={onTouchEnd}
|
onTouchend={onTouchEnd}
|
||||||
onTouchcancel={onTouchEnd}
|
onTouchcancel={onTouchEnd}
|
||||||
onClick={stopPropagation}
|
onClick={stopPropagation}
|
||||||
@ -320,6 +321,11 @@ export default defineComponent({
|
|||||||
updateValue(props.modelValue);
|
updateValue(props.modelValue);
|
||||||
useCustomFieldValue(() => props.modelValue);
|
useCustomFieldValue(() => props.modelValue);
|
||||||
|
|
||||||
|
// useEventListener will set passive to `false` to eliminate the warning of Chrome
|
||||||
|
useEventListener('touchmove', onTouchMove, {
|
||||||
|
target: slider,
|
||||||
|
});
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<div
|
<div
|
||||||
ref={root}
|
ref={root}
|
||||||
|
@ -21,7 +21,7 @@ import {
|
|||||||
} from '../utils';
|
} from '../utils';
|
||||||
|
|
||||||
// Composables
|
// Composables
|
||||||
import { useRect, useClickAway } from '@vant/use';
|
import { useRect, useClickAway, useEventListener } from '@vant/use';
|
||||||
import { useTouch } from '../composables/use-touch';
|
import { useTouch } from '../composables/use-touch';
|
||||||
import { useExpose } from '../composables/use-expose';
|
import { useExpose } from '../composables/use-expose';
|
||||||
|
|
||||||
@ -209,6 +209,11 @@ export default defineComponent({
|
|||||||
|
|
||||||
useClickAway(root, () => onClick('outside'), { eventName: 'touchstart' });
|
useClickAway(root, () => onClick('outside'), { eventName: 'touchstart' });
|
||||||
|
|
||||||
|
// useEventListener will set passive to `false` to eliminate the warning of Chrome
|
||||||
|
useEventListener('touchmove', onTouchMove, {
|
||||||
|
target: root,
|
||||||
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const wrapperStyle = {
|
const wrapperStyle = {
|
||||||
transform: `translate3d(${state.offset}px, 0, 0)`,
|
transform: `translate3d(${state.offset}px, 0, 0)`,
|
||||||
@ -221,7 +226,6 @@ export default defineComponent({
|
|||||||
class={bem()}
|
class={bem()}
|
||||||
onClick={getClickHandler('cell', lockClick)}
|
onClick={getClickHandler('cell', lockClick)}
|
||||||
onTouchstartPassive={onTouchStart}
|
onTouchstartPassive={onTouchStart}
|
||||||
onTouchmove={onTouchMove}
|
|
||||||
onTouchend={onTouchEnd}
|
onTouchend={onTouchEnd}
|
||||||
onTouchcancel={onTouchEnd}
|
onTouchcancel={onTouchEnd}
|
||||||
>
|
>
|
||||||
|
@ -28,7 +28,12 @@ import {
|
|||||||
} from '../utils';
|
} from '../utils';
|
||||||
|
|
||||||
// Composables
|
// Composables
|
||||||
import { doubleRaf, useChildren, usePageVisibility } from '@vant/use';
|
import {
|
||||||
|
doubleRaf,
|
||||||
|
useChildren,
|
||||||
|
useEventListener,
|
||||||
|
usePageVisibility,
|
||||||
|
} from '@vant/use';
|
||||||
import { useTouch } from '../composables/use-touch';
|
import { useTouch } from '../composables/use-touch';
|
||||||
import { useExpose } from '../composables/use-expose';
|
import { useExpose } from '../composables/use-expose';
|
||||||
import { onPopupReopen } from '../composables/on-popup-reopen';
|
import { onPopupReopen } from '../composables/on-popup-reopen';
|
||||||
@ -66,6 +71,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
setup(props, { emit, slots }) {
|
setup(props, { emit, slots }) {
|
||||||
const root = ref<HTMLElement>();
|
const root = ref<HTMLElement>();
|
||||||
|
const track = ref<HTMLElement>();
|
||||||
const state = reactive<SwipeState>({
|
const state = reactive<SwipeState>({
|
||||||
rect: null,
|
rect: null,
|
||||||
width: 0,
|
width: 0,
|
||||||
@ -301,10 +307,17 @@ export default defineComponent({
|
|||||||
touch.move(event);
|
touch.move(event);
|
||||||
|
|
||||||
if (isCorrectDirection.value) {
|
if (isCorrectDirection.value) {
|
||||||
|
const isEdgeTouch =
|
||||||
|
!props.loop &&
|
||||||
|
((state.active === 0 && delta.value > 0) ||
|
||||||
|
(state.active === count.value - 1 && delta.value < 0));
|
||||||
|
|
||||||
|
if (!isEdgeTouch) {
|
||||||
preventDefault(event, props.stopPropagation);
|
preventDefault(event, props.stopPropagation);
|
||||||
move({ offset: delta.value });
|
move({ offset: delta.value });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onTouchEnd = () => {
|
const onTouchEnd = () => {
|
||||||
@ -435,13 +448,18 @@ export default defineComponent({
|
|||||||
onDeactivated(stopAutoplay);
|
onDeactivated(stopAutoplay);
|
||||||
onBeforeUnmount(stopAutoplay);
|
onBeforeUnmount(stopAutoplay);
|
||||||
|
|
||||||
|
// useEventListener will set passive to `false` to eliminate the warning of Chrome
|
||||||
|
useEventListener('touchmove', onTouchMove, {
|
||||||
|
target: track,
|
||||||
|
});
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<div ref={root} class={bem()}>
|
<div ref={root} class={bem()}>
|
||||||
<div
|
<div
|
||||||
|
ref={track}
|
||||||
style={trackStyle.value}
|
style={trackStyle.value}
|
||||||
class={bem('track', { vertical: props.vertical })}
|
class={bem('track', { vertical: props.vertical })}
|
||||||
onTouchstartPassive={onTouchStart}
|
onTouchstartPassive={onTouchStart}
|
||||||
onTouchmove={onTouchMove}
|
|
||||||
onTouchend={onTouchEnd}
|
onTouchend={onTouchEnd}
|
||||||
onTouchcancel={onTouchEnd}
|
onTouchcancel={onTouchEnd}
|
||||||
>
|
>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user