componentInstance.ts 3.0 KB
Newer Older
fxy060608's avatar
fxy060608 已提交
1
import { ComponentPublicInstance } from 'vue'
fxy060608's avatar
fxy060608 已提交
2
import { extend } from '@vue/shared'
fxy060608's avatar
fxy060608 已提交
3
import { normalizeTarget } from '@dcloudio/uni-shared'
fxy060608's avatar
fxy060608 已提交
4
import { getWindowOffset } from '../../helpers'
fxy060608's avatar
fxy060608 已提交
5

fxy060608's avatar
fxy060608 已提交
6 7 8
const isClickEvent = (val: Event): val is MouseEvent => val.type === 'click'
const isMouseEvent = (val: Event): val is MouseEvent =>
  val.type.indexOf('mouse') === 0
fxy060608's avatar
fxy060608 已提交
9 10
// normalizeNativeEvent
export function $nne(this: ComponentPublicInstance, evt: Event) {
fxy060608's avatar
fxy060608 已提交
11 12
  // 目前内置组件底层实现,当需要访问原始event时,请使用withWebEvent包裹
  // 用法参考:uni-h5/src/framework/components/page/page-refresh/index.ts
fxy060608's avatar
fxy060608 已提交
13 14 15 16
  const { currentTarget } = evt
  if (!(evt instanceof Event) || !(currentTarget instanceof HTMLElement)) {
    return evt
  }
fxy060608's avatar
fxy060608 已提交
17
  if (currentTarget.tagName.indexOf('UNI-') !== 0) {
fxy060608's avatar
fxy060608 已提交
18 19 20 21 22 23
    return evt
  }

  const res = createNativeEvent(evt)

  if (isClickEvent(evt)) {
24
    normalizeClickEvent(res as unknown as WechatMiniprogram.Touch, evt)
fxy060608's avatar
fxy060608 已提交
25
  } else if (__PLATFORM__ === 'h5' && isMouseEvent(evt)) {
26
    normalizeMouseEvent(res as unknown as WechatMiniprogram.Touch, evt)
fxy060608's avatar
fxy060608 已提交
27 28 29 30
  } else if (evt instanceof TouchEvent) {
    const { top } = getWindowOffset()
    ;(res as any).touches = normalizeTouchEvent(evt.touches, top)
    ;(res as any).changedTouches = normalizeTouchEvent(evt.changedTouches, top)
fxy060608's avatar
fxy060608 已提交
31 32 33 34 35
  }

  return res
}

36
export function createNativeEvent(evt: Event | TouchEvent) {
fxy060608's avatar
fxy060608 已提交
37 38
  const { type, timeStamp, currentTarget } = evt
  const target = normalizeTarget(currentTarget as HTMLElement)
fxy060608's avatar
fxy060608 已提交
39
  const event = {
fxy060608's avatar
fxy060608 已提交
40 41 42 43 44 45
    type,
    timeStamp,
    target,
    detail: {},
    currentTarget: target,
  }
46 47 48 49
  if (evt.type.startsWith('touch')) {
    ;(event as any).touches = (evt as TouchEvent).touches
    ;(event as any).changedTouches = (evt as TouchEvent).changedTouches
  }
fxy060608's avatar
fxy060608 已提交
50 51 52 53 54 55 56 57 58 59 60
  if (__PLATFORM__ === 'h5') {
    extend(event, {
      preventDefault() {
        return evt.preventDefault()
      },
      stopPropagation() {
        return evt.stopPropagation()
      },
    })
  }
  return event
fxy060608's avatar
fxy060608 已提交
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
}

function normalizeClickEvent(
  evt: WechatMiniprogram.Touch,
  mouseEvt: MouseEvent
) {
  const { x, y } = mouseEvt
  const { top } = getWindowOffset()
  evt.detail = { x, y: y - top }
  evt.touches = evt.changedTouches = [createTouchEvent(mouseEvt)]
}

function normalizeMouseEvent(evt: Record<string, any>, mouseEvt: MouseEvent) {
  const { top } = getWindowOffset()
  evt.pageX = mouseEvt.pageX
  evt.pageY = mouseEvt.pageY - top
  evt.clientX = mouseEvt.clientX
  evt.clientY = mouseEvt.clientY - top
fxy060608's avatar
fxy060608 已提交
79 80
}

fxy060608's avatar
fxy060608 已提交
81 82 83 84 85 86 87 88
function createTouchEvent(evt: MouseEvent) {
  return {
    force: 1,
    identifier: 0,
    clientX: evt.clientX,
    clientY: evt.clientY,
    pageX: evt.pageX,
    pageY: evt.pageY,
fxy060608's avatar
fxy060608 已提交
89 90
  }
}
fxy060608's avatar
fxy060608 已提交
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106

function normalizeTouchEvent(touches: TouchList, top: number) {
  const res = []
  for (let i = 0; i < touches.length; i++) {
    const { identifier, pageX, pageY, clientX, clientY, force } = touches[i]
    res.push({
      identifier,
      pageX,
      pageY: pageY - top,
      clientX: clientX,
      clientY: clientY - top,
      force: force || 0,
    })
  }
  return res
}