page.ts 4.6 KB
Newer Older
fxy060608's avatar
fxy060608 已提交
1 2 3 4 5 6
import {
  createScrollListener,
  CreateScrollListenerOptions,
  disableScrollListener,
  updateCssVar,
} from '@dcloudio/uni-core'
fxy060608's avatar
fxy060608 已提交
7 8 9 10 11 12
import {
  formatLog,
  ON_PAGE_SCROLL,
  ON_REACH_BOTTOM,
  PageCreateData,
  UniNodeJSON,
Q
qiang 已提交
13
  scrollTo,
fxy060608's avatar
fxy060608 已提交
14
} from '@dcloudio/uni-shared'
fxy060608's avatar
fxy060608 已提交
15 16 17

import { UniElement } from './elements/UniElement'
import { UniNode } from './elements/UniNode'
fxy060608's avatar
fxy060608 已提交
18
import { BuiltInComponents } from './components'
fxy060608's avatar
fxy060608 已提交
19 20 21 22

const elements = new Map<number, UniNode>()

export function $(id: number) {
fxy060608's avatar
fxy060608 已提交
23
  return elements.get(id) as UniElement<any>
fxy060608's avatar
fxy060608 已提交
24 25
}

fxy060608's avatar
fxy060608 已提交
26 27 28 29 30 31 32
export function removeElement(id: number) {
  if (__DEV__) {
    console.log(formatLog('Remove', id, elements.size - 1))
  }
  return elements.delete(id)
}

fxy060608's avatar
fxy060608 已提交
33 34
export function createElement(
  id: number,
fxy060608's avatar
fxy060608 已提交
35
  tag: string,
fxy060608's avatar
fxy060608 已提交
36
  parentNodeId: number,
fxy060608's avatar
fxy060608 已提交
37
  refNodeId: number,
fxy060608's avatar
fxy060608 已提交
38 39
  nodeJson: Partial<UniNodeJSON> = {}
) {
fxy060608's avatar
fxy060608 已提交
40
  let element: UniNode
fxy060608's avatar
fxy060608 已提交
41 42 43 44 45
  if (id === 0) {
    // initPageElement
    element = new UniNode(
      id,
      tag as string,
fxy060608's avatar
fxy060608 已提交
46
      parentNodeId,
fxy060608's avatar
fxy060608 已提交
47 48
      document.createElement(tag as string)
    )
fxy060608's avatar
fxy060608 已提交
49
  } else {
fxy060608's avatar
fxy060608 已提交
50 51
    const Component = BuiltInComponents[tag as keyof typeof BuiltInComponents]
    if (Component) {
fxy060608's avatar
fxy060608 已提交
52
      element = new Component(id, parentNodeId, refNodeId, nodeJson)
fxy060608's avatar
fxy060608 已提交
53 54 55 56 57
    } else {
      element = new UniElement(
        id,
        document.createElement(tag),
        parentNodeId,
fxy060608's avatar
fxy060608 已提交
58
        refNodeId,
fxy060608's avatar
fxy060608 已提交
59 60 61
        nodeJson
      )
    }
fxy060608's avatar
fxy060608 已提交
62 63 64 65
  }
  elements.set(id, element)
  return element
}
fxy060608's avatar
fxy060608 已提交
66

fxy060608's avatar
fxy060608 已提交
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
const pageReadyCallbacks: (() => void)[] = []
let isPageReady = false
export function onPageReady(callback: () => void) {
  if (isPageReady) {
    return callback()
  }
  pageReadyCallbacks.push(callback)
}

function setPageReady() {
  if (__DEV__) {
    console.log(formatLog('setPageReady', pageReadyCallbacks.length))
  }
  isPageReady = true
  pageReadyCallbacks.forEach((fn) => fn())
  pageReadyCallbacks.length = 0
}

fxy060608's avatar
fxy060608 已提交
85
export function onPageCreated() {}
fxy060608's avatar
fxy060608 已提交
86 87

export function onPageCreate({
fxy060608's avatar
fxy060608 已提交
88
  css,
fxy060608's avatar
fxy060608 已提交
89
  route,
fxy060608's avatar
fxy060608 已提交
90 91 92
  platform,
  pixelRatio,
  windowWidth,
fxy060608's avatar
fxy060608 已提交
93 94 95 96 97 98 99 100
  disableScroll,
  onPageScroll,
  onPageReachBottom,
  onReachBottomDistance,
  statusbarHeight,
  windowTop,
  windowBottom,
}: PageCreateData) {
fxy060608's avatar
fxy060608 已提交
101
  initPageInfo(route)
fxy060608's avatar
fxy060608 已提交
102
  initSystemInfo(platform, pixelRatio, windowWidth)
fxy060608's avatar
fxy060608 已提交
103 104 105
  // 初始化页面容器元素
  initPageElement()

fxy060608's avatar
fxy060608 已提交
106 107 108 109 110 111 112 113 114 115 116
  const pageId = plus.webview.currentWebview().id!
  ;(window as any).__id__ = pageId
  document.title = `${route}[${pageId}]`

  initCssVar(statusbarHeight, windowTop, windowBottom)

  if (disableScroll) {
    document.addEventListener('touchmove', disableScrollListener)
  } else if (onPageScroll || onPageReachBottom) {
    initPageScroll(onPageScroll, onPageReachBottom, onReachBottomDistance)
  }
fxy060608's avatar
fxy060608 已提交
117 118 119 120 121 122

  if (css) {
    initPageCss(route)
  } else {
    setPageReady()
  }
fxy060608's avatar
fxy060608 已提交
123 124
}

fxy060608's avatar
fxy060608 已提交
125 126 127 128 129 130
function initPageInfo(route: string) {
  ;(window as any).__PAGE_INFO__ = {
    route,
  }
}

fxy060608's avatar
fxy060608 已提交
131 132 133 134 135 136 137 138 139 140 141 142
function initSystemInfo(
  platform: string,
  pixelRatio: number,
  windowWidth: number
) {
  ;(window as any).__SYSTEM_INFO__ = {
    platform,
    pixelRatio,
    windowWidth,
  }
}

fxy060608's avatar
fxy060608 已提交
143
function initPageElement() {
fxy060608's avatar
fxy060608 已提交
144
  createElement(0, 'div', -1, -1).$ = document.getElementById('app')!
fxy060608's avatar
fxy060608 已提交
145 146 147
}

function initPageCss(route: string) {
fxy060608's avatar
fxy060608 已提交
148 149 150
  if (__DEV__) {
    console.log(formatLog('initPageCss', route + '.css'))
  }
fxy060608's avatar
fxy060608 已提交
151 152 153 154
  const element = document.createElement('link')
  element.type = 'text/css'
  element.rel = 'stylesheet'
  element.href = route + '.css'
fxy060608's avatar
fxy060608 已提交
155 156
  element.onload = setPageReady
  element.onerror = setPageReady
fxy060608's avatar
fxy060608 已提交
157 158 159
  document.head.appendChild(element)
}

fxy060608's avatar
fxy060608 已提交
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
function initCssVar(
  statusbarHeight: number,
  windowTop: number,
  windowBottom: number
) {
  const cssVars = {
    '--window-left': '0px',
    '--window-right': '0px',
    '--window-top': windowTop + 'px',
    '--window-bottom': windowBottom + 'px',
    '--status-bar-height': statusbarHeight + 'px',
  }
  if (__DEV__) {
    console.log(formatLog('initCssVar', cssVars))
  }
  updateCssVar(cssVars)
}

function initPageScroll(
  onPageScroll: boolean,
  onPageReachBottom: boolean,
  onReachBottomDistance: number
) {
  const opts: CreateScrollListenerOptions = {}
  if (onPageScroll) {
    opts.onPageScroll = (scrollTop) => {
fxy060608's avatar
fxy060608 已提交
186
      UniViewJSBridge.publishHandler(ON_PAGE_SCROLL, { scrollTop })
fxy060608's avatar
fxy060608 已提交
187 188 189 190
    }
  }
  if (onPageReachBottom) {
    opts.onReachBottomDistance = onReachBottomDistance
fxy060608's avatar
fxy060608 已提交
191
    opts.onReachBottom = () => UniViewJSBridge.publishHandler(ON_REACH_BOTTOM)
fxy060608's avatar
fxy060608 已提交
192 193 194 195 196 197
  }
  // 避免监听太早,直接触发了 scroll
  requestAnimationFrame(() =>
    document.addEventListener('scroll', createScrollListener(opts))
  )
}
Q
qiang 已提交
198 199 200 201 202 203 204 205 206 207 208 209

export function pageScrollTo(
  {
    scrollTop,
    selector,
    duration,
  }: { selector?: string; scrollTop?: number; duration?: number },
  publish: (err?: string) => void
) {
  scrollTo(selector! || scrollTop! || 0, duration!)
  publish()
}