index.tsx 3.4 KB
Newer Older
D
DCloud_LXH 已提交
1 2 3 4 5 6 7 8 9
import {
  ref,
  onMounted,
  Ref,
  onActivated,
  onDeactivated,
  watchEffect,
  onBeforeUnmount,
} from 'vue'
10
import { hasOwn } from '@vue/shared'
D
DCloud_LXH 已提交
11
import {
12 13 14 15
  defineBuiltInComponent,
  ResizeSensor,
  useAttrs,
} from '@dcloudio/uni-components'
D
DCloud_LXH 已提交
16
import { getRealPath } from '@dcloudio/uni-platform'
D
DCloud_LXH 已提交
17 18 19 20 21
import {
  updateElementStyle,
  once,
  ON_WEB_INVOKE_APP_SERVICE,
} from '@dcloudio/uni-shared'
D
DCloud_LXH 已提交
22 23 24
import { onWebInvokeAppService } from '../../../service/onWebInvokeAppService'

const Invoke = /*#__PURE__*/ once(() =>
D
DCloud_LXH 已提交
25
  UniServiceJSBridge.on(ON_WEB_INVOKE_APP_SERVICE, onWebInvokeAppService)
D
DCloud_LXH 已提交
26
)
D
DCloud_LXH 已提交
27 28 29 30 31 32

const props = {
  src: {
    type: String,
    default: '',
  },
33 34 35 36
  fullscreen: {
    type: Boolean,
    default: true,
  },
D
DCloud_LXH 已提交
37 38 39 40
}

type RootRef = Ref<HTMLElement | null>

41
export default /*#__PURE__*/ defineBuiltInComponent({
D
DCloud_LXH 已提交
42
  inheritAttrs: false,
D
DCloud_LXH 已提交
43 44
  name: 'WebView',
  props,
D
DCloud_LXH 已提交
45
  setup(props) {
D
DCloud_LXH 已提交
46
    Invoke()
D
DCloud_LXH 已提交
47
    const rootRef: RootRef = ref(null)
D
DCloud_LXH 已提交
48
    const iframeRef: RootRef = ref(null)
D
DCloud_LXH 已提交
49 50 51
    const { $attrs, $excludeAttrs, $listeners } = useAttrs({
      excludeListeners: true,
    })
D
DCloud_LXH 已提交
52
    let _resize: Function
D
DCloud_LXH 已提交
53

D
DCloud_LXH 已提交
54 55 56 57
    const renderIframe = () => {
      const iframe = document.createElement('iframe')
      watchEffect(() => {
        for (const key in $attrs.value) {
58
          if (hasOwn($attrs.value, key)) {
D
DCloud_LXH 已提交
59 60 61 62 63 64 65 66
            const attr = ($attrs.value as any)[key]
            ;(iframe as any)[key] = attr
          }
        }
      })
      watchEffect(() => {
        iframe.src = getRealPath(props.src)
      })
67 68 69 70 71 72
      _resize = useWebViewSize(rootRef, iframe, props.fullscreen)
      if(props.fullscreen){
        document.body.appendChild(iframe)
      }else{
        iframeRef.value = iframe
      }
D
DCloud_LXH 已提交
73 74 75
    }

    __NODE_JS__ ? onMounted(renderIframe) : renderIframe()
D
DCloud_LXH 已提交
76 77
    onMounted(() => {
      _resize()
78
      !props.fullscreen && rootRef.value?.appendChild(iframeRef.value!)
D
DCloud_LXH 已提交
79
    })
D
DCloud_LXH 已提交
80

D
DCloud_LXH 已提交
81 82 83
    onActivated(() => {
      iframeRef.value && (iframeRef.value.style.display = 'block')
    })
D
DCloud_LXH 已提交
84

D
DCloud_LXH 已提交
85 86 87
    onDeactivated(() => {
      iframeRef.value && (iframeRef.value.style.display = 'none')
    })
D
DCloud_LXH 已提交
88

D
DCloud_LXH 已提交
89
    onBeforeUnmount(() => {
90
      iframeRef.value && document.body.removeChild(iframeRef.value)
D
DCloud_LXH 已提交
91 92
    })

D
DCloud_LXH 已提交
93 94 95
    return () => {
      return (
        <>
D
DCloud_LXH 已提交
96
          <uni-web-view
97
            class={props.fullscreen ? 'uni-webview--fullscreen': ''}
D
DCloud_LXH 已提交
98 99 100 101
            {...$listeners.value}
            {...$excludeAttrs.value}
            ref={rootRef}
          >
102
            {/* @ts-ignore */}
D
DCloud_LXH 已提交
103 104
            <ResizeSensor onResize={_resize} />
          </uni-web-view>
D
DCloud_LXH 已提交
105

D
DCloud_LXH 已提交
106 107
          {/* TODO 等待teleport组件支持ssr */}
          {/* <Teleport to="body">
D
DCloud_LXH 已提交
108 109 110
            <iframe
              ref={iframeRef}
              src={getRealPath(props.src)}
D
DCloud_LXH 已提交
111
              {...$attrs.value}
D
DCloud_LXH 已提交
112
            ></iframe>
D
DCloud_LXH 已提交
113
          </Teleport> */}
D
DCloud_LXH 已提交
114 115
        </>
      )
D
DCloud_LXH 已提交
116
    }
D
DCloud_LXH 已提交
117 118
  },
})
D
DCloud_LXH 已提交
119

120
function useWebViewSize(rootRef: RootRef, iframe: HTMLIFrameElement, fullscreen:boolean) {
D
DCloud_LXH 已提交
121
  const _resize = () => {
122 123 124
    if(fullscreen){
      const { top, left, width, height } = rootRef.value!.getBoundingClientRect()
      updateElementStyle(iframe, {
D
DCloud_LXH 已提交
125 126 127 128 129 130 131 132
        position: 'absolute',
        display: 'block',
        border: '0',
        top: top + 'px',
        left: left + 'px',
        width: width + 'px',
        height: height + 'px',
      })
133 134 135 136 137 138
    }else{
      updateElementStyle(iframe, {
        width: rootRef.value?.style.width || '300px',
        height: rootRef.value?.style.height || '150px',
      })
    }
D
DCloud_LXH 已提交
139 140
  }

D
DCloud_LXH 已提交
141
  return _resize
D
DCloud_LXH 已提交
142
}