Skip to content

Commit f4fcf7a

Browse files
authored
fix(vue-directive): unify the functions in vue-hooks into double-layer functions and optimize the infinite-scroll function (#2864)
1 parent 2581baa commit f4fcf7a

File tree

7 files changed

+67
-122
lines changed

7 files changed

+67
-122
lines changed

packages/renderless/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
},
3838
"dependencies": {
3939
"@opentiny/utils": "workspace:~",
40-
"@opentiny/vue-directive": "workspace:~",
4140
"@opentiny/vue-hooks": "workspace:~",
4241
"color": "4.2.3"
4342
},

packages/renderless/src/recycle-scroller/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getScrollContainer } from '@opentiny/vue-directive'
1+
import { getScrollContainer } from '@opentiny/utils'
22
import { isNull } from '@opentiny/utils'
33

44
let supportsPassive = false

packages/vue-directive/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
import AutoTip from './src/auto-tip'
1414
import Clickoutside from './src/clickoutside'
1515
import HighlightQuery from './src/highlight-query'
16+
import InfiniteScroll from './src/infinite-scroll'
1617
import ObserveVisibility from './src/observe-visibility'
1718
import RepeatClick from './src/repeat-click'
1819

19-
export { InfiniteScroll, getScrollContainer } from './src/infinite-scroll'
20-
export { AutoTip, HighlightQuery, Clickoutside, RepeatClick, ObserveVisibility }
20+
export { AutoTip, HighlightQuery, Clickoutside, RepeatClick, ObserveVisibility, InfiniteScroll }

packages/vue-directive/src/infinite-scroll.ts

Lines changed: 2 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { throttle } from '@opentiny/utils'
2+
import { getScrollContainer } from '@opentiny/utils'
23

34
const CONTEXT_KEY = '@@infinitescrollContext'
45
const OBSERVER_CHECK_INTERVAL = 50
@@ -107,56 +108,6 @@ function observerChecker(el, cb) {
107108
}
108109
}
109110

110-
const cached = (fn) => {
111-
const cache = Object.create(null)
112-
return (str) => cache[str] || (cache[str] = fn(str))
113-
}
114-
115-
const camelizeRE = /-(\w)/g
116-
117-
const camelize = cached((str) => str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : '')))
118-
119-
/** TINY_DUP dom.ts */
120-
const getElementStyle = (elem, styleKey) => {
121-
if (!elem || !styleKey) return ''
122-
123-
let key = camelize(styleKey)
124-
125-
if (key === 'float') key = 'cssFloat'
126-
127-
try {
128-
const styleValue = elem.style[key]
129-
130-
if (styleValue) return styleValue
131-
132-
const computedStyle = document.defaultView ? document.defaultView.getComputedStyle(elem, '') : null
133-
134-
return computedStyle ? computedStyle[key] : ''
135-
} catch (e) {
136-
return elem.style[key]
137-
}
138-
}
139-
/** TINY_DUP dom.ts */
140-
const canScroll = (el, isVertical) => {
141-
const overflowKey = { undefined: 'overflow', true: 'overflow-y', false: 'overflow-x' }[String(isVertical)]
142-
const overflowVal = getElementStyle(el, overflowKey)
143-
return ['scroll', 'auto', 'overlay'].some((s) => overflowVal.includes(s))
144-
}
145-
/** TINY_DUP dom.ts */
146-
export const getScrollContainer = (el, isVertical) => {
147-
let parentEl = el
148-
149-
while (parentEl) {
150-
if ([window, document, document.documentElement].includes(parentEl)) return window
151-
152-
if (canScroll(parentEl, isVertical)) return parentEl
153-
154-
parentEl = parentEl.parentNode
155-
}
156-
157-
return parentEl
158-
}
159-
160111
const bind = (el, binding, vnode) => {
161112
const instance = binding.instance || vnode.context
162113
const { value: cb } = binding
@@ -211,7 +162,7 @@ const unbind = (el) => {
211162
stopObserver(el)
212163
}
213164

214-
export const InfiniteScroll = {
165+
export default {
215166
bind,
216167
update,
217168
unbind,

packages/vue-hooks/package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
},
1616
"dependencies": {
1717
"@floating-ui/dom": "^1.6.9",
18-
"@opentiny/utils": "workspace:~",
19-
"@opentiny/vue-common": "workspace:~"
18+
"@opentiny/utils": "workspace:~"
2019
}
21-
}
20+
}

packages/vue-hooks/src/use-floating.ts

Lines changed: 52 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
import type { Placement, Strategy, OffsetOptions, RootBoundary, Boundary, ReferenceElement } from '@floating-ui/dom'
22
import { computePosition, autoUpdate, flip, offset, shift, arrow, hide, limitShift } from '@floating-ui/dom'
33

4-
import { hooks } from '@opentiny/vue-common'
5-
6-
const { reactive, watch, markRaw, onBeforeUnmount } = hooks
7-
84
interface IFloatOption {
95
reference: null | ReferenceElement
106
popper: null | HTMLElement
@@ -330,7 +326,7 @@ const emit = (state: IFloatOption, eventName: string, params?: any) => {
330326
}
331327

332328
/** 快速构建虚拟元素的辅助方法, 适于右键菜单,区域选择, 跟随光标等场景 */
333-
const virtualEl = (x: number, y: number, w: number = 0, h: number = 0) => ({
329+
const virtualEl = (x: number, y: number, w = 0, h = 0) => ({
334330
getBoundingClientRect() {
335331
return {
336332
width: 0,
@@ -346,66 +342,68 @@ const virtualEl = (x: number, y: number, w: number = 0, h: number = 0) => ({
346342
})
347343

348344
/** 响应式的弹出层管理函数,适用于场景: tooltip, poppover, select, 右键菜单, floatbar, notify, 或 canvas上跟随鼠标等 */
349-
export const useFloating = (option: Partial<IFloatOption> = {}) => {
350-
const state = reactive(option) as IFloatOption
345+
export const useFloating =
346+
({ reactive, watch, markRaw, onBeforeUnmount }) =>
347+
(option: Partial<IFloatOption> = {}) => {
348+
const state = reactive(option) as IFloatOption
351349

352-
let cleanup: null | (() => void) = null
350+
let cleanup: null | (() => void) = null
353351

354-
// 0、标准化state
355-
Object.keys(defaultOption).forEach((key) => {
356-
if (!Object.prototype.hasOwnProperty.call(state, key)) {
357-
state[key] = defaultOption[key]
358-
}
359-
})
360-
state._last = markRaw({}) as any
361-
state._events = markRaw({ show: [], hide: [], update: [] })
362-
363-
const watchState = () => {
364-
// 1、引用和弹窗同时存在
365-
if (state.popper && state.reference) {
366-
// 1.1 当前需要显示, 可能是show变化了,也可能是其它任意值变化了, 都需要重新的一次update
367-
if (state.show) {
368-
appendPopper(state)
369-
if (state.autoUpdate) {
352+
// 0、标准化state
353+
Object.keys(defaultOption).forEach((key) => {
354+
if (!Object.prototype.hasOwnProperty.call(state, key)) {
355+
state[key] = defaultOption[key]
356+
}
357+
})
358+
state._last = markRaw({}) as any
359+
state._events = markRaw({ show: [], hide: [], update: [] })
360+
361+
const watchState = () => {
362+
// 1、引用和弹窗同时存在
363+
if (state.popper && state.reference) {
364+
// 1.1 当前需要显示, 可能是show变化了,也可能是其它任意值变化了, 都需要重新的一次update
365+
if (state.show) {
366+
appendPopper(state)
367+
if (state.autoUpdate) {
368+
cleanup && cleanup()
369+
cleanup = autoUpdatePopper(state)
370+
} else {
371+
updatePopper(state)
372+
}
373+
}
374+
// 1.2 当前不需要显示
375+
else {
370376
cleanup && cleanup()
371-
cleanup = autoUpdatePopper(state)
372-
} else {
373-
updatePopper(state)
377+
closePopper(state)
374378
}
375379
}
376-
// 1.2 当前不需要显示
380+
// 2、引用和弹窗不全。 可能前一次是全的,所以要释放一下
377381
else {
378382
cleanup && cleanup()
379383
closePopper(state)
380384
}
381-
}
382-
// 2、引用和弹窗不全。 可能前一次是全的,所以要释放一下
383-
else {
384-
cleanup && cleanup()
385-
closePopper(state)
386-
}
387385

388-
state._last.popper = state.popper
389-
state._last.reference = state.reference
390-
state._last.show = (state.show && state.popper && state.reference) as boolean // 真实的是否show变量
391-
state._last.appendToBody = state.appendToBody
392-
state._last.timestamp = new Date().getTime()
393-
}
386+
state._last.popper = state.popper
387+
state._last.reference = state.reference
388+
state._last.show = (state.show && state.popper && state.reference) as boolean // 真实的是否show变量
389+
state._last.appendToBody = state.appendToBody
390+
state._last.timestamp = new Date().getTime()
391+
}
394392

395-
watch(state, watchState, { immediate: true })
393+
watch(state, watchState, { immediate: true })
396394

397-
const on = (eventName, cb) => state._events[eventName].push(cb)
398-
const off = (eventName, cb) => (state._events[eventName] = state._events[eventName].filter((i) => i !== cb))
395+
const on = (eventName, cb) => state._events[eventName].push(cb)
396+
const off = (eventName, cb) => (state._events[eventName] = state._events[eventName].filter((i) => i !== cb))
399397

400-
// 3、组件卸载前,移除元素
401-
onBeforeUnmount(() => {
402-
cleanup && cleanup()
403-
closePopper(state)
404-
})
398+
// 3、组件卸载前,移除元素
399+
onBeforeUnmount(() => {
400+
cleanup && cleanup()
401+
closePopper(state)
402+
})
405403

406-
// 4、返回state 及辅助方法
407-
// 正常修改state去触发更新,但如果某些业务想在state不变时,仍想执行一次更新, 则使用forceUpdate即可
408-
// 比如select 懒加载: popper, show都不变, 但popper 的大小变化了,可以forceUpdate一下。
409-
// 【autoUpdate 理论上会监听 popper的resize的, 这层考虑可能是多余。】
410-
return { state, on, off, virtualEl, forceUpdate: watchState }
411-
}
404+
// 4、返回state 及辅助方法
405+
// 正常修改state去触发更新,但如果某些业务想在state不变时,仍想执行一次更新, 则使用forceUpdate即可
406+
// 比如select 懒加载: popper, show都不变, 但popper 的大小变化了,可以forceUpdate一下。
407+
// 【autoUpdate 理论上会监听 popper的resize的, 这层考虑可能是多余。】
408+
return { state, on, off, virtualEl, forceUpdate: watchState }
409+
}
Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
import { hooks } from '@opentiny/vue-common'
2-
3-
const { ref, watch, isRef } = hooks
4-
51
/** 慢加载的 v-show 的办法, 灵感来自于: https://github.com/antfu/v-lazy-show
62
* 适用场景: 存在初始加载时,不需要显示的区域,但又需要用v-show切换显示。 比如 tabs\collapse\dropdown\cascader\carousel等
73
* @example
@@ -12,11 +8,13 @@ const { ref, watch, isRef } = hooks
128
* isShow 第一次为true时,才会加载该DOM
139
* </div>
1410
*/
15-
export const useLazyShow = (show) => {
16-
const lazyShow = ref(isRef(show) ? show.value : show)
11+
export const useLazyShow =
12+
({ ref, watch, isRef }) =>
13+
(show) => {
14+
const lazyShow = ref(isRef(show) ? show.value : show)
1715

18-
if (!lazyShow.value) {
19-
const stop = watch(show, (v) => v && (lazyShow.value = true) && stop(), { flush: 'sync' })
16+
if (!lazyShow.value) {
17+
const stop = watch(show, (v) => v && (lazyShow.value = true) && stop(), { flush: 'sync' })
18+
}
19+
return { lazyShow }
2020
}
21-
return { lazyShow }
22-
}

0 commit comments

Comments
 (0)