mirror of
https://gitee.com/wot-design-uni/wot-design-uni.git
synced 2025-12-06 17:18:40 +08:00
refactor: ♻️ 重构使用 requestAnimationFrame 的逻辑修复微信小程序报错方法重复定义的问题 (#749)
✅ Closes: #549
This commit is contained in:
parent
c136f54cda
commit
e9b147ea96
@ -443,7 +443,7 @@ export const requestAnimationFrame = (cb = () => {}) => {
|
||||
* @param ms 延迟时间
|
||||
* @returns
|
||||
*/
|
||||
export const pause = (ms: number) => {
|
||||
export const pause = (ms: number = 1000 / 30) => {
|
||||
return new AbortablePromise((resolve) => {
|
||||
const timer = setTimeout(() => {
|
||||
clearTimeout(timer)
|
||||
|
||||
@ -63,7 +63,7 @@ export default {
|
||||
<script lang="ts" setup>
|
||||
import wdPickerView from '../../wd-picker-view/wd-picker-view.vue'
|
||||
import { computed, ref, watch, onMounted } from 'vue'
|
||||
import { debounce, isArray, isEqual, isNumber, requestAnimationFrame } from '../../common/util'
|
||||
import { debounce, isArray, isEqual, isNumber, pause } from '../../common/util'
|
||||
import { compareMonth, formatMonthTitle, getMonthEndDay, getMonths, getTimeData, getWeekLabel } from '../utils'
|
||||
import Month from '../month/month.vue'
|
||||
import { monthPanelProps, type MonthInfo, type MonthPanelTimeType, type MonthPanelExpose } from './types'
|
||||
@ -185,8 +185,9 @@ onMounted(() => {
|
||||
/**
|
||||
* 使当前日期或者选中日期滚动到可视区域
|
||||
*/
|
||||
function scrollIntoView() {
|
||||
requestAnimationFrame(() => {
|
||||
async function scrollIntoView() {
|
||||
// 等待渲染完毕
|
||||
await pause()
|
||||
let activeDate: number | null = 0
|
||||
if (isArray(props.value)) {
|
||||
activeDate = props.value![0]
|
||||
@ -206,10 +207,9 @@ function scrollIntoView() {
|
||||
top += months.value[index] ? Number(months.value[index].height) : 0
|
||||
}
|
||||
scrollTop.value = 0
|
||||
requestAnimationFrame(() => {
|
||||
// 等待渲染完毕
|
||||
await pause()
|
||||
scrollTop.value = top
|
||||
})
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 获取时间 picker 的数据
|
||||
|
||||
@ -33,7 +33,7 @@ export default {
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, onMounted } from 'vue'
|
||||
import { compareYear, formatYearTitle, getYears } from '../utils'
|
||||
import { isArray, isNumber, requestAnimationFrame } from '../../common/util'
|
||||
import { isArray, isNumber, pause } from '../../common/util'
|
||||
import Year from '../year/year.vue'
|
||||
import { yearPanelProps, type YearInfo, type YearPanelExpose } from './types'
|
||||
|
||||
@ -68,8 +68,8 @@ onMounted(() => {
|
||||
scrollIntoView()
|
||||
})
|
||||
|
||||
function scrollIntoView() {
|
||||
requestAnimationFrame(() => {
|
||||
async function scrollIntoView() {
|
||||
await pause()
|
||||
let activeDate: number | null = null
|
||||
if (isArray(props.value)) {
|
||||
activeDate = props.value![0]
|
||||
@ -89,10 +89,8 @@ function scrollIntoView() {
|
||||
top += years.value[index] ? Number(years.value[index].height) : 0
|
||||
}
|
||||
scrollTop.value = 0
|
||||
requestAnimationFrame(() => {
|
||||
await pause()
|
||||
scrollTop.value = top
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const yearScroll = (event: { detail: { scrollTop: number } }) => {
|
||||
|
||||
@ -122,7 +122,7 @@ import wdActionSheet from '../wd-action-sheet/wd-action-sheet.vue'
|
||||
import wdButton from '../wd-button/wd-button.vue'
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { dayjs } from '../common/dayjs'
|
||||
import { deepClone, isArray, isEqual, padZero, requestAnimationFrame } from '../common/util'
|
||||
import { deepClone, isArray, isEqual, padZero, pause } from '../common/util'
|
||||
import { getWeekNumber, isRange } from '../wd-calendar-view/utils'
|
||||
import { useCell } from '../composables/useCell'
|
||||
import { FORM_KEY, type FormItemRule } from '../wd-form/types'
|
||||
@ -313,7 +313,7 @@ function scrollIntoView() {
|
||||
calendarView.value && calendarView.value && calendarView.value.$.exposed.scrollIntoView()
|
||||
}
|
||||
// 对外暴露方法
|
||||
function open() {
|
||||
async function open() {
|
||||
const { disabled, readonly } = props
|
||||
|
||||
if (disabled || readonly) return
|
||||
@ -323,10 +323,9 @@ function open() {
|
||||
lastCalendarValue.value = deepClone(calendarValue.value)
|
||||
lastTab.value = currentTab.value
|
||||
lastCurrentType.value = currentType.value
|
||||
requestAnimationFrame(() => {
|
||||
// 等待渲染完毕
|
||||
await pause()
|
||||
scrollIntoView()
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
if (props.showTypeSwitch) {
|
||||
calendarTabs.value.scrollIntoView()
|
||||
|
||||
@ -32,7 +32,7 @@ export default {
|
||||
<script lang="ts" setup>
|
||||
import wdIcon from '../wd-icon/wd-icon.vue'
|
||||
import { computed, getCurrentInstance, onMounted, ref, watch, type CSSProperties } from 'vue'
|
||||
import { addUnit, getRect, isArray, isDef, isPromise, isString, objToStyle, requestAnimationFrame, uuid } from '../common/util'
|
||||
import { addUnit, getRect, isArray, isDef, isPromise, isString, objToStyle, pause, uuid } from '../common/util'
|
||||
import { useParent } from '../composables/useParent'
|
||||
import { COLLAPSE_KEY } from '../wd-collapse/types'
|
||||
import { collapseItemProps, type CollapseItemExpose } from './types'
|
||||
@ -103,10 +103,10 @@ async function updateExpand(useBeforeExpand: boolean = true) {
|
||||
}
|
||||
|
||||
function initRect() {
|
||||
getRect(`#${collapseId.value}`, false, proxy).then((rect) => {
|
||||
getRect(`#${collapseId.value}`, false, proxy).then(async (rect) => {
|
||||
const { height: rectHeight } = rect
|
||||
height.value = isDef(rectHeight) ? Number(rectHeight) : ''
|
||||
requestAnimationFrame(() => {
|
||||
await pause()
|
||||
if (isSelected.value) {
|
||||
expanded.value = true
|
||||
} else {
|
||||
@ -116,7 +116,6 @@ function initRect() {
|
||||
inited.value = true
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function handleTransitionEnd() {
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
import type { AnchorIndex } from './type'
|
||||
import { indexBarInjectionKey, indexBarProps } from './type'
|
||||
import { ref, getCurrentInstance, onMounted, reactive, nextTick, watch } from 'vue'
|
||||
import { getRect, isDef, uuid, requestAnimationFrame } from '../common/util'
|
||||
import { getRect, isDef, uuid, pause } from '../common/util'
|
||||
import { useChildren } from '../composables/useChildren'
|
||||
|
||||
const props = defineProps(indexBarProps)
|
||||
@ -131,13 +131,12 @@ function handleTouchMove(e: TouchEvent) {
|
||||
setScrollTop(getAnchorByPageY(clientY).$.exposed!.top.value - offsetTop)
|
||||
}
|
||||
|
||||
function handleTouchEnd(e: TouchEvent) {
|
||||
async function handleTouchEnd(e: TouchEvent) {
|
||||
const clientY = e.changedTouches[0].pageY
|
||||
state.activeIndex = getAnchorByPageY(clientY).index
|
||||
setScrollTop(getAnchorByPageY(clientY).$.exposed!.top.value - offsetTop)
|
||||
requestAnimationFrame(() => {
|
||||
await pause()
|
||||
scrollState.touching = false
|
||||
})
|
||||
}
|
||||
|
||||
function setScrollTop(top: number) {
|
||||
|
||||
@ -87,7 +87,7 @@ export default {
|
||||
<script lang="ts" setup>
|
||||
import wdIcon from '../wd-icon/wd-icon.vue'
|
||||
import { computed, onBeforeMount, ref, watch } from 'vue'
|
||||
import { isDef, objToStyle, pause, requestAnimationFrame } from '../common/util'
|
||||
import { isDef, objToStyle, pause } from '../common/util'
|
||||
import { useCell } from '../composables/useCell'
|
||||
import { FORM_KEY, type FormItemRule } from '../wd-form/types'
|
||||
import { useParent } from '../composables/useParent'
|
||||
@ -230,14 +230,14 @@ function formatValue(value: string | number) {
|
||||
function togglePwdVisible() {
|
||||
isPwdVisible.value = !isPwdVisible.value
|
||||
}
|
||||
function handleClear() {
|
||||
async function handleClear() {
|
||||
clearing.value = true
|
||||
focusing.value = false
|
||||
inputValue.value = ''
|
||||
if (props.focusWhenClear) {
|
||||
focused.value = false
|
||||
}
|
||||
requestAnimationFrame(() => {
|
||||
await pause()
|
||||
if (props.focusWhenClear) {
|
||||
focused.value = true
|
||||
focusing.value = true
|
||||
@ -247,7 +247,6 @@ function handleClear() {
|
||||
})
|
||||
emit('update:modelValue', inputValue.value)
|
||||
emit('clear')
|
||||
})
|
||||
}
|
||||
async function handleBlur() {
|
||||
// 等待150毫秒,clear执行完毕
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
<template>
|
||||
<view :class="rootClass" :style="customStyle">
|
||||
<!--自定义label插槽-->
|
||||
<!--搜索框主体-->
|
||||
<view class="wd-search__block">
|
||||
<slot name="prefix"></slot>
|
||||
<view class="wd-search__field">
|
||||
@ -9,9 +7,7 @@
|
||||
<wd-icon name="search" custom-class="wd-search__search-icon"></wd-icon>
|
||||
<text class="wd-search__placeholder-txt">{{ placeholder || translate('search') }}</text>
|
||||
</view>
|
||||
<!--icon:search-->
|
||||
<wd-icon v-if="showInput || str || placeholderLeft" name="search" custom-class="wd-search__search-left-icon"></wd-icon>
|
||||
<!--搜索框-->
|
||||
<input
|
||||
v-if="showInput || str || placeholderLeft"
|
||||
:placeholder="placeholder || translate('search')"
|
||||
@ -27,14 +23,11 @@
|
||||
:maxlength="maxlength"
|
||||
:focus="isFocused"
|
||||
/>
|
||||
<!--icon:clear-->
|
||||
<wd-icon v-if="str" custom-class="wd-search__clear wd-search__clear-icon" name="error-fill" @click="clearSearch" />
|
||||
</view>
|
||||
</view>
|
||||
<!--the button behind input,care for hideCancel without displaying-->
|
||||
|
||||
<slot v-if="!hideCancel" name="suffix">
|
||||
<!--默认button-->
|
||||
<view class="wd-search__cancel" @click="handleCancel">
|
||||
{{ cancelTxt || translate('cancel') }}
|
||||
</view>
|
||||
@ -56,7 +49,7 @@ export default {
|
||||
<script lang="ts" setup>
|
||||
import wdIcon from '../wd-icon/wd-icon.vue'
|
||||
import { type CSSProperties, computed, onMounted, ref, watch } from 'vue'
|
||||
import { objToStyle, requestAnimationFrame } from '../common/util'
|
||||
import { objToStyle, pause } from '../common/util'
|
||||
import { useTranslate } from '../composables/useTranslate'
|
||||
import { searchProps } from './types'
|
||||
|
||||
@ -110,22 +103,17 @@ const coverStyle = computed(() => {
|
||||
return objToStyle(coverStyle)
|
||||
})
|
||||
|
||||
function hackFocus(focus: boolean) {
|
||||
async function hackFocus(focus: boolean) {
|
||||
showInput.value = focus
|
||||
requestAnimationFrame(() => {
|
||||
await pause()
|
||||
isFocused.value = focus
|
||||
})
|
||||
}
|
||||
|
||||
function closeCover() {
|
||||
async function closeCover() {
|
||||
if (props.disabled) return
|
||||
requestAnimationFrame()
|
||||
.then(() => requestAnimationFrame())
|
||||
.then(() => requestAnimationFrame())
|
||||
.then(() => {
|
||||
await pause(100)
|
||||
showPlaceHolder.value = false
|
||||
hackFocus(true)
|
||||
})
|
||||
}
|
||||
/**
|
||||
* @description input的input事件handle
|
||||
@ -141,16 +129,13 @@ function inputValue(event: any) {
|
||||
/**
|
||||
* @description 点击清空icon的handle
|
||||
*/
|
||||
function clearSearch() {
|
||||
async function clearSearch() {
|
||||
str.value = ''
|
||||
clearing.value = true
|
||||
if (props.focusWhenClear) {
|
||||
isFocused.value = false
|
||||
}
|
||||
requestAnimationFrame()
|
||||
.then(() => requestAnimationFrame())
|
||||
.then(() => requestAnimationFrame())
|
||||
.then(() => {
|
||||
await pause(100)
|
||||
if (props.focusWhenClear) {
|
||||
showPlaceHolder.value = false
|
||||
hackFocus(true)
|
||||
@ -163,7 +148,6 @@ function clearSearch() {
|
||||
})
|
||||
emit('update:modelValue', '')
|
||||
emit('clear')
|
||||
})
|
||||
}
|
||||
/**
|
||||
* @description 点击搜索按钮时的handle
|
||||
|
||||
@ -32,7 +32,7 @@ export default {
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, getCurrentInstance, onMounted, reactive, watch } from 'vue'
|
||||
import { requestAnimationFrame, getRect, isObj, objToStyle, addUnit } from '../common/util'
|
||||
import { getRect, isObj, objToStyle, addUnit, pause } from '../common/util'
|
||||
import type { CSSProperties } from 'vue'
|
||||
import { segmentedProps, type SegmentedExpose, type SegmentedOption } from './types'
|
||||
const $item = '.wd-segmented__item'
|
||||
@ -65,11 +65,10 @@ watch(
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
onMounted(() => {
|
||||
onMounted(async () => {
|
||||
updateCurrentIndex()
|
||||
requestAnimationFrame(() => {
|
||||
await pause()
|
||||
updateActiveStyle(false)
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
|
||||
@ -128,7 +128,7 @@ import wdLoading from '../wd-loading/wd-loading.vue'
|
||||
|
||||
import { getCurrentInstance, onBeforeMount, ref, watch, nextTick, computed } from 'vue'
|
||||
import { useCell } from '../composables/useCell'
|
||||
import { getRect, isArray, isDef, isFunction, requestAnimationFrame } from '../common/util'
|
||||
import { getRect, isArray, isDef, isFunction, pause } from '../common/util'
|
||||
import { useParent } from '../composables/useParent'
|
||||
import { FORM_KEY, type FormItemRule } from '../wd-form/types'
|
||||
import { useTranslate } from '../composables/useTranslate'
|
||||
@ -261,7 +261,7 @@ onBeforeMount(() => {
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
function setScrollIntoView() {
|
||||
async function setScrollIntoView() {
|
||||
let wraperSelector: string = ''
|
||||
let selectorPromise: Promise<UniApp.NodeInfo>[] = []
|
||||
if (isDef(selectList.value) && selectList.value !== '' && !isArray(selectList.value)) {
|
||||
@ -274,8 +274,7 @@ function setScrollIntoView() {
|
||||
wraperSelector = '#wd-checkbox-group'
|
||||
}
|
||||
if (wraperSelector) {
|
||||
requestAnimationFrame().then(() => {
|
||||
requestAnimationFrame().then(() => {
|
||||
await pause(2000 / 30)
|
||||
Promise.all([getRect('.wd-select-picker__wrapper', false, proxy), getRect(wraperSelector, false, proxy), ...selectorPromise]).then((res) => {
|
||||
if (isDef(res) && isArray(res)) {
|
||||
const scrollView = res[0]
|
||||
@ -294,8 +293,6 @@ function setScrollIntoView() {
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ export default {
|
||||
<script lang="ts" setup>
|
||||
import wdResize from '../wd-resize/wd-resize.vue'
|
||||
import { computed, getCurrentInstance, reactive, ref, type CSSProperties } from 'vue'
|
||||
import { addUnit, getRect, objToStyle, requestAnimationFrame, uuid } from '../common/util'
|
||||
import { addUnit, getRect, objToStyle, pause, uuid } from '../common/util'
|
||||
import { stickyProps } from './types'
|
||||
import { useParent } from '../composables/useParent'
|
||||
import { STICKY_BOX_KEY } from '../wd-sticky-box/types'
|
||||
@ -108,14 +108,13 @@ function createObserver() {
|
||||
/**
|
||||
* 当前内容高度发生变化时重置监听
|
||||
*/
|
||||
function handleResize(detail: any) {
|
||||
async function handleResize(detail: any) {
|
||||
stickyState.width = detail.width
|
||||
stickyState.height = detail.height
|
||||
requestAnimationFrame(() => {
|
||||
await pause()
|
||||
observerContentScroll()
|
||||
if (!stickyBox || !stickyBox.observerForChild) return
|
||||
stickyBox.observerForChild(proxy)
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 监听吸顶元素滚动事件
|
||||
|
||||
@ -74,7 +74,7 @@ export default {
|
||||
<script lang="ts" setup>
|
||||
import wdIcon from '../wd-icon/wd-icon.vue'
|
||||
import { computed, onBeforeMount, ref, watch } from 'vue'
|
||||
import { objToStyle, requestAnimationFrame, isDef, pause } from '../common/util'
|
||||
import { objToStyle, isDef, pause } from '../common/util'
|
||||
import { useCell } from '../composables/useCell'
|
||||
import { FORM_KEY, type FormItemRule } from '../wd-form/types'
|
||||
import { useParent } from '../composables/useParent'
|
||||
@ -221,14 +221,14 @@ function formatValue(value: string | number) {
|
||||
return `${value}`
|
||||
}
|
||||
|
||||
function handleClear() {
|
||||
async function handleClear() {
|
||||
clearing.value = true
|
||||
focusing.value = false
|
||||
inputValue.value = ''
|
||||
if (props.focusWhenClear) {
|
||||
focused.value = false
|
||||
}
|
||||
requestAnimationFrame(() => {
|
||||
await pause()
|
||||
if (props.focusWhenClear) {
|
||||
focused.value = true
|
||||
focusing.value = true
|
||||
@ -238,7 +238,6 @@ function handleClear() {
|
||||
})
|
||||
emit('update:modelValue', inputValue.value)
|
||||
emit('clear')
|
||||
})
|
||||
}
|
||||
async function handleBlur({ detail }: any) {
|
||||
// 等待150毫秒,clear执行完毕
|
||||
|
||||
@ -17,7 +17,7 @@ export default {
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onBeforeMount, ref, watch } from 'vue'
|
||||
import { isObj, isPromise, requestAnimationFrame } from '../common/util'
|
||||
import { isObj, isPromise, pause } from '../common/util'
|
||||
import { transitionProps, type TransitionName } from './types'
|
||||
import { AbortablePromise } from '../common/AbortablePromise'
|
||||
|
||||
@ -127,16 +127,16 @@ function enter() {
|
||||
const duration = isObj(props.duration) ? (props.duration as any).enter : props.duration
|
||||
status.value = 'enter'
|
||||
emit('before-enter')
|
||||
enterLifeCyclePromises.value = requestAnimationFrame()
|
||||
enterLifeCyclePromises.value = pause()
|
||||
await enterLifeCyclePromises.value
|
||||
emit('enter')
|
||||
classes.value = classNames.enter
|
||||
currentDuration.value = duration
|
||||
enterLifeCyclePromises.value = requestAnimationFrame()
|
||||
enterLifeCyclePromises.value = pause()
|
||||
await enterLifeCyclePromises.value
|
||||
inited.value = true
|
||||
display.value = true
|
||||
enterLifeCyclePromises.value = requestAnimationFrame()
|
||||
enterLifeCyclePromises.value = pause()
|
||||
await enterLifeCyclePromises.value
|
||||
enterLifeCyclePromises.value = null
|
||||
transitionEnded.value = false
|
||||
@ -162,11 +162,11 @@ async function leave() {
|
||||
status.value = 'leave'
|
||||
emit('before-leave')
|
||||
currentDuration.value = duration
|
||||
leaveLifeCyclePromises.value = requestAnimationFrame()
|
||||
leaveLifeCyclePromises.value = pause()
|
||||
await leaveLifeCyclePromises.value
|
||||
emit('leave')
|
||||
classes.value = classNames.leave
|
||||
leaveLifeCyclePromises.value = requestAnimationFrame()
|
||||
leaveLifeCyclePromises.value = pause()
|
||||
await leaveLifeCyclePromises.value
|
||||
transitionEnded.value = false
|
||||
classes.value = classNames['leave-to']
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user