'a'
mh-two-thousand-and-two
2024-04-12 44d2c92345cd156a59fc327b3060292a282d2893
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import 'intersection-observer'
 
import {
  getTargetDataset
} from 'uni-helpers/index'
 
import {
  findElm
} from './util'
 
function getRect (rect) {
  return {
    bottom: rect.bottom,
    height: rect.height,
    left: rect.left,
    right: rect.right,
    top: rect.top,
    width: rect.width
  }
}
 
// 在相交比很小的情况下,Chrome会返回相交为0
function rectifyIntersectionRatio (entrie) {
  const {
    intersectionRatio,
    boundingClientRect: { height: overAllHeight, width: overAllWidth },
    intersectionRect: { height: intersectionHeight, width: intersectionWidth }
  } = entrie
 
  if (intersectionRatio !== 0) return intersectionRatio
 
  return intersectionHeight === overAllHeight
    ? intersectionWidth / overAllWidth
    : intersectionHeight / overAllHeight
}
 
const intersectionObservers = {}
 
export function requestComponentObserver ({
  reqId,
  component,
  options
}, pageId) {
  let pageVm
  if (pageId._isVue) {
    pageVm = pageId
  } else {
    const pages = getCurrentPages() // 跨平台时,View 层也应该实现该方法,举例 App 上,View 层的 getCurrentPages 返回长度为1的当前页面数组
    const page = pages.find(page => page.$page.id === pageId)
    if (!page) {
      throw new Error(`Not Found:Page[${pageId}]`)
    }
    pageVm = page.$vm
  }
  const $el = findElm(component, pageVm)
  const root = options.relativeToSelector ? $el.querySelector(options.relativeToSelector) : null
  const intersectionObserver = intersectionObservers[reqId] = new IntersectionObserver((entries, observer) => {
    entries.forEach(entrie => {
      UniViewJSBridge.publishHandler('onRequestComponentObserver', {
        reqId,
        res: {
          intersectionRatio: rectifyIntersectionRatio(entrie),
          intersectionRect: getRect(entrie.intersectionRect),
          boundingClientRect: getRect(entrie.boundingClientRect),
          relativeRect: getRect(entrie.rootBounds),
          time: Date.now(),
          dataset: getTargetDataset(entrie.target),
          id: entrie.target.id
        }
      })
    })
  }, {
    root,
    rootMargin: options.rootMargin,
    threshold: options.thresholds
  })
  if (options.observeAll) {
    intersectionObserver.USE_MUTATION_OBSERVER = true
    Array.prototype.map.call($el.querySelectorAll(options.selector), el => {
      if (!el) {
        console.warn(`Node ${options.selector} is not found. Intersection observer will not trigger.`)
        return
      }
      intersectionObserver.observe(el)
    })
  } else {
    intersectionObserver.USE_MUTATION_OBSERVER = false
    const el = $el.querySelector(options.selector)
    if (!el) {
      console.warn(`Node ${options.selector} is not found. Intersection observer will not trigger.`)
      return
    }
    intersectionObserver.observe(el)
  }
}
 
export function destroyComponentObserver ({
  reqId
}) {
  const intersectionObserver = intersectionObservers[reqId]
  if (intersectionObserver) {
    intersectionObserver.disconnect()
    delete intersectionObservers[reqId]
    UniViewJSBridge.publishHandler('onRequestComponentObserver', {
      reqId,
      reqEnd: true
    })
  }
}