init
This commit is contained in:
11
uni_modules/nutui-uni/components/_hooks/index.ts
Normal file
11
uni_modules/nutui-uni/components/_hooks/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export * from './useExpose'
|
||||
export * from './useGlobalZIndex'
|
||||
export * from './useInject'
|
||||
export * from './useLockScroll'
|
||||
export * from './useProvide'
|
||||
export * from './useRect'
|
||||
export * from './useRelation'
|
||||
export * from './useRouter'
|
||||
export * from './useSelectorQuery'
|
||||
export * from './useStyle'
|
||||
export * from './useTouch'
|
||||
8
uni_modules/nutui-uni/components/_hooks/useExpose.ts
Normal file
8
uni_modules/nutui-uni/components/_hooks/useExpose.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import type { ComponentPublicInstance } from 'vue'
|
||||
import { getCurrentInstance } from 'vue'
|
||||
|
||||
export function useExpose(apis: Record<string, any>) {
|
||||
const instance = getCurrentInstance()
|
||||
if (instance)
|
||||
Object.assign(instance.proxy as ComponentPublicInstance, apis)
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
let globalZIndex = 2000
|
||||
|
||||
export function useGlobalZIndex() {
|
||||
return ++globalZIndex
|
||||
}
|
||||
|
||||
export function setGlobalZIndex(value: number) {
|
||||
globalZIndex = value
|
||||
}
|
||||
32
uni_modules/nutui-uni/components/_hooks/useInject.ts
Normal file
32
uni_modules/nutui-uni/components/_hooks/useInject.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { computed, getCurrentInstance, inject, onUnmounted, ref } from 'vue'
|
||||
import type { ComponentInternalInstance, InjectionKey } from 'vue'
|
||||
|
||||
type ParentProvide<T> = T & {
|
||||
add: (child: ComponentInternalInstance) => void
|
||||
remove: (child: ComponentInternalInstance) => void
|
||||
internalChildren: ComponentInternalInstance[]
|
||||
}
|
||||
|
||||
export function useInject<T>(key: InjectionKey<ParentProvide<T>>) {
|
||||
const parent = inject(key, null)
|
||||
|
||||
if (parent) {
|
||||
const instance = getCurrentInstance()!
|
||||
const { add, remove, internalChildren } = parent
|
||||
|
||||
add(instance)
|
||||
onUnmounted(() => remove(instance))
|
||||
|
||||
const index = computed(() => internalChildren.indexOf(instance))
|
||||
|
||||
return {
|
||||
parent,
|
||||
index,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
parent: null,
|
||||
index: ref(-1),
|
||||
}
|
||||
}
|
||||
31
uni_modules/nutui-uni/components/_hooks/useLockScroll.ts
Normal file
31
uni_modules/nutui-uni/components/_hooks/useLockScroll.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
let count = 0
|
||||
|
||||
const CLSNAME = 'nut-overflow-hidden'
|
||||
|
||||
export function useLockScroll(isLock: () => boolean) {
|
||||
const lock = () => {
|
||||
if (isLock()) {
|
||||
try {
|
||||
!count && document.body.classList.add(CLSNAME)
|
||||
count++
|
||||
}
|
||||
catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const unlock = () => {
|
||||
if (isLock() && count) {
|
||||
try {
|
||||
count--
|
||||
!count && document.body.classList.remove(CLSNAME)
|
||||
}
|
||||
catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [lock, unlock]
|
||||
}
|
||||
93
uni_modules/nutui-uni/components/_hooks/useProvide.ts
Normal file
93
uni_modules/nutui-uni/components/_hooks/useProvide.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import { getCurrentInstance, markRaw, provide, shallowReactive } from 'vue'
|
||||
import type {
|
||||
ComponentInternalInstance,
|
||||
ConcreteComponent,
|
||||
InjectionKey,
|
||||
VNode,
|
||||
VNodeNormalizedChildren,
|
||||
} from 'vue'
|
||||
|
||||
// TODO: uniapp 不支持 vue 直接导出的 isVNode
|
||||
export function isVNode(value: any): value is VNode {
|
||||
return value ? value.__v_isVNode === true : false
|
||||
}
|
||||
|
||||
export function flattenVNodes(shouldTraverseChildren: VNodeNormalizedChildren, childName?: string) {
|
||||
const result: VNode[] = []
|
||||
|
||||
const traverse = (children: VNodeNormalizedChildren) => {
|
||||
if (!Array.isArray(children))
|
||||
return
|
||||
children.forEach((child) => {
|
||||
if (!isVNode(child))
|
||||
return
|
||||
|
||||
if (childName) {
|
||||
if (child.type && (child.type as ConcreteComponent).name === childName) {
|
||||
result.push(child)
|
||||
return
|
||||
}
|
||||
}
|
||||
else {
|
||||
result.push(child)
|
||||
}
|
||||
|
||||
if (child.component?.subTree)
|
||||
traverse(child.component.subTree.children)
|
||||
|
||||
if (child.children)
|
||||
traverse(child.children)
|
||||
})
|
||||
}
|
||||
|
||||
traverse(shouldTraverseChildren)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
export function sortChildren(
|
||||
parent: ComponentInternalInstance,
|
||||
internalChildren: ComponentInternalInstance[],
|
||||
childName?: string,
|
||||
) {
|
||||
const vnodes = flattenVNodes(parent && parent.subTree && parent.subTree.children, childName)
|
||||
internalChildren.sort((a, b) => {
|
||||
return vnodes.indexOf(a.vnode) - vnodes.indexOf(b.vnode)
|
||||
})
|
||||
}
|
||||
|
||||
// 如果指定组件名称,则只查找此组件并且查到后结束。也就是不关心此组件下的内容,在大部分场景下节省查找消耗。
|
||||
export function useProvide<ProvideValue>(key: InjectionKey<ProvideValue>, childName?: string) {
|
||||
const internalChildren: ComponentInternalInstance[] = shallowReactive([])
|
||||
const publicChildren = shallowReactive<any[]>([])
|
||||
const parent = getCurrentInstance()!
|
||||
|
||||
const add = (child: ComponentInternalInstance) => {
|
||||
if (!child.proxy)
|
||||
return
|
||||
internalChildren.push(markRaw(child))
|
||||
publicChildren.push(markRaw(child.proxy))
|
||||
sortChildren(parent, internalChildren, childName)
|
||||
}
|
||||
|
||||
const remove = (child: ComponentInternalInstance) => {
|
||||
if (child.proxy) {
|
||||
internalChildren.splice(internalChildren.indexOf(markRaw(child)), 1)
|
||||
publicChildren.splice(publicChildren.indexOf(markRaw(child.proxy)), 1)
|
||||
}
|
||||
}
|
||||
|
||||
return (value?: ProvideValue) => {
|
||||
provide(key, {
|
||||
add,
|
||||
remove,
|
||||
internalChildren,
|
||||
...value,
|
||||
} as any)
|
||||
|
||||
return {
|
||||
internalChildren,
|
||||
children: publicChildren,
|
||||
}
|
||||
}
|
||||
}
|
||||
7
uni_modules/nutui-uni/components/_hooks/useRect.ts
Normal file
7
uni_modules/nutui-uni/components/_hooks/useRect.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import type { ComponentInternalInstance } from 'vue'
|
||||
import { useSelectorQuery } from './useSelectorQuery'
|
||||
|
||||
export function useRect(id: string, instance?: ComponentInternalInstance): Promise<UniApp.NodeInfo> {
|
||||
const { getSelectorNodeInfo } = useSelectorQuery(instance)
|
||||
return getSelectorNodeInfo(`#${id}`)
|
||||
}
|
||||
8
uni_modules/nutui-uni/components/_hooks/useRelation.ts
Normal file
8
uni_modules/nutui-uni/components/_hooks/useRelation.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import type { ComponentPublicInstance } from 'vue'
|
||||
import { getCurrentInstance } from 'vue'
|
||||
|
||||
export function useExtend<T>(apis: T) {
|
||||
const instance = getCurrentInstance()
|
||||
if (instance)
|
||||
Object.assign(instance.proxy as ComponentPublicInstance, apis)
|
||||
}
|
||||
28
uni_modules/nutui-uni/components/_hooks/useRouter.ts
Normal file
28
uni_modules/nutui-uni/components/_hooks/useRouter.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
export type NavigateToOptions = string | UniApp.NavigateToOptions
|
||||
export type RedirectToOptions = string | UniApp.RedirectToOptions
|
||||
|
||||
export type RouterOptions = UniApp.NavigateToOptions | UniApp.RedirectToOptions
|
||||
|
||||
export function useRouter() {
|
||||
const push = (options: NavigateToOptions) => {
|
||||
if (typeof options === 'string') {
|
||||
uni.navigateTo({ url: options })
|
||||
return
|
||||
}
|
||||
|
||||
uni.navigateTo(options)
|
||||
}
|
||||
const replace = (options: RedirectToOptions) => {
|
||||
if (typeof options === 'string') {
|
||||
uni.redirectTo({ url: options })
|
||||
return
|
||||
}
|
||||
|
||||
uni.redirectTo(options)
|
||||
}
|
||||
|
||||
return {
|
||||
push,
|
||||
replace,
|
||||
}
|
||||
}
|
||||
67
uni_modules/nutui-uni/components/_hooks/useSelectorQuery.ts
Normal file
67
uni_modules/nutui-uni/components/_hooks/useSelectorQuery.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { getCurrentInstance } from 'vue'
|
||||
import type { ComponentInternalInstance } from 'vue'
|
||||
|
||||
export function useSelectorQuery(instance?: ComponentInternalInstance | null) {
|
||||
let query: UniApp.SelectorQuery | null = null
|
||||
|
||||
if (!instance)
|
||||
instance = getCurrentInstance()
|
||||
|
||||
if (!instance)
|
||||
console.warn('useSelectorQuery', 'useSelectorQuery必须在setup函数中使用')
|
||||
|
||||
// #ifndef MP-ALIPAY
|
||||
query = uni.createSelectorQuery().in(instance)
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
query = uni.createSelectorQuery().in(null)
|
||||
// #endif
|
||||
|
||||
const getSelectorNodeInfo = (selector: string): Promise<UniApp.NodeInfo> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (query) {
|
||||
query
|
||||
.select(selector)
|
||||
.boundingClientRect((res) => {
|
||||
const selectRes: UniApp.NodeInfo = res as UniApp.NodeInfo
|
||||
if (selectRes)
|
||||
resolve(selectRes)
|
||||
else
|
||||
reject(new Error(`未找到对应节点: ${selector}`))
|
||||
})
|
||||
.exec()
|
||||
}
|
||||
else {
|
||||
reject(new Error('未找到对应的SelectorQuery实例'))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getSelectorNodeInfos = (
|
||||
selector: string,
|
||||
): Promise<UniApp.NodeInfo[]> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (query) {
|
||||
query
|
||||
.selectAll(selector)
|
||||
.boundingClientRect((res) => {
|
||||
const selectRes: UniApp.NodeInfo[] = res as UniApp.NodeInfo[]
|
||||
if (selectRes && selectRes.length > 0)
|
||||
resolve(selectRes)
|
||||
else
|
||||
reject(new Error(`未找到对应节点: ${selector}`))
|
||||
})
|
||||
.exec()
|
||||
}
|
||||
else {
|
||||
reject(new Error('未找到对应的SelectorQuery实例'))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
query,
|
||||
getSelectorNodeInfo,
|
||||
getSelectorNodeInfos,
|
||||
}
|
||||
}
|
||||
29
uni_modules/nutui-uni/components/_hooks/useStyle.ts
Normal file
29
uni_modules/nutui-uni/components/_hooks/useStyle.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { computed, normalizeClass, normalizeStyle } from 'vue'
|
||||
import { stringifyStyle } from '../_utils'
|
||||
|
||||
export function useStyleContext(props: any, componentName: string) {
|
||||
const mainClass = computed(() => {
|
||||
const cls = normalizeClass([props.customClass, { [componentName]: true }])
|
||||
|
||||
return cls
|
||||
})
|
||||
|
||||
const mainStyle = computed(() => {
|
||||
return stringifyStyle(normalizeStyle(props.customStyle))
|
||||
})
|
||||
|
||||
const getMainClass = (cls: unknown) => {
|
||||
return normalizeClass([props.customClass, { [componentName]: true }, cls])
|
||||
}
|
||||
|
||||
const getMainStyle = (style: unknown) => {
|
||||
return stringifyStyle(normalizeStyle([props.customStyle, style]))
|
||||
}
|
||||
|
||||
return {
|
||||
mainClass,
|
||||
mainStyle,
|
||||
getMainClass,
|
||||
getMainStyle,
|
||||
}
|
||||
}
|
||||
74
uni_modules/nutui-uni/components/_hooks/useTouch.ts
Normal file
74
uni_modules/nutui-uni/components/_hooks/useTouch.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { ref } from 'vue'
|
||||
|
||||
const MIN_DISTANCE = 10
|
||||
|
||||
type Direction = '' | 'vertical' | 'horizontal'
|
||||
|
||||
function getDirection(x: number, y: number) {
|
||||
if (x > y && x > MIN_DISTANCE)
|
||||
return 'horizontal'
|
||||
|
||||
if (y > x && y > MIN_DISTANCE)
|
||||
return 'vertical'
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
export function useTouch() {
|
||||
const startX = ref(0)
|
||||
const startY = ref(0)
|
||||
const moveX = ref(0)
|
||||
const moveY = ref(0)
|
||||
const deltaX = ref(0)
|
||||
const deltaY = ref(0)
|
||||
const offsetX = ref(0)
|
||||
const offsetY = ref(0)
|
||||
const direction = ref<Direction>('')
|
||||
|
||||
const isVertical = () => direction.value === 'vertical'
|
||||
const isHorizontal = () => direction.value === 'horizontal'
|
||||
|
||||
const reset = () => {
|
||||
deltaX.value = 0
|
||||
deltaY.value = 0
|
||||
offsetX.value = 0
|
||||
offsetY.value = 0
|
||||
direction.value = ''
|
||||
}
|
||||
|
||||
const start = ((event: TouchEvent) => {
|
||||
reset()
|
||||
startX.value = event.touches[0].clientX
|
||||
startY.value = event.touches[0].clientY
|
||||
}) as EventListener
|
||||
|
||||
const move = ((event: TouchEvent) => {
|
||||
const touch = event.touches[0]
|
||||
deltaX.value = touch.clientX - startX.value
|
||||
deltaY.value = touch.clientY - startY.value
|
||||
moveX.value = touch.clientX
|
||||
moveY.value = touch.clientY
|
||||
offsetX.value = Math.abs(deltaX.value)
|
||||
offsetY.value = Math.abs(deltaY.value)
|
||||
|
||||
if (!direction.value)
|
||||
direction.value = getDirection(offsetX.value, offsetY.value)
|
||||
}) as EventListener
|
||||
|
||||
return {
|
||||
move,
|
||||
start,
|
||||
reset,
|
||||
startX,
|
||||
startY,
|
||||
moveX,
|
||||
moveY,
|
||||
deltaX,
|
||||
deltaY,
|
||||
offsetX,
|
||||
offsetY,
|
||||
direction,
|
||||
isVertical,
|
||||
isHorizontal,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user