4***@qq.com
4***@qq.com
  • 发布:2022-01-21 11:22
  • 更新:2022-07-07 09:06
  • 阅读:2920

uniapp vue3如何获取appWebView?

分类:uni-app

老的写法是这样获取

onReady() {  
  this.$parent.$getAppWebview().children()[0]  
}

切换到vue3 setup script后,@dcloudio/uni-app下有一个onReady的函数,但是没有this.$parent了,那么如何获取appWebView对象呢?

2022-01-21 11:22 负责人:无 分享
已邀请:
水车

水车

楼主,解决了吗?我也遇到了同样的问题

4***@qq.com

4***@qq.com (作者)

这是我目前用的办法,每隔50毫秒尝试获取一次,重试20次还获取不到则报错。一般情况下200毫秒内可以获取成功

<template>  
  <web-view :src="s.url" @message="s.onPostMessage"></web-view>  
</template>  

<script setup lang="ts">  
import {tryGet} from '../../util/tryGet'  
import {showModal} from '../../util/modal'  
import {handleMessage} from '../../util/postMessage'  
import {react} from '../../util/react'  
import {onBackPress, onLoad, onReady} from '@dcloudio/uni-app'  
import {getCurrentInstance} from 'vue'  

const s = react(() => new class {  
  appWebview: any = null  
  canBack = false  
  url = ''  
  onPostMessage(e: any) {  
    console.debug('receive post message:', e)  
    const m = e.detail.data[0] || {}  
    handleMessage(m)  
  }  
  getAppWebview() {  
    if (s.appWebview) return s.appWebview  
    else if (s.appWebview === undefined) showModal('错误', 'webview初始化失败,请退出重试')  
    else uni.showToast({  
        title: '加载中,请稍候',  
        icon: 'loading'  
      })  
  }  
}())  

const { proxy }  = getCurrentInstance()!  
console.debug('proxy: %o', proxy)  
onReady(async () => {  
  // #ifdef APP-PLUS  
  const parent = proxy!.$parent! as any // todo use getCurrentPages() instead?  
  s.appWebview = await tryGet(() => parent.$getAppWebview().children()[0], 50, 20)  
  const wv = s.getAppWebview()  
  if (!wv) return  
  //允许双指缩放  
  wv.setStyle({  
    scalable: true  
  })  
  //每当webview地址发生变化,更新是否允许后退的flag  
  wv.addEventListener('loaded', () => wv.canBack((e: any) => s.canBack = e.canBack))  
  //todo 拦截a标签文件下载(如果不拦截使用原生的链接跳转,页面会显示错误,且无下载进度,也不能直接安装下载后的安装包)  
  // #endif  
})  

onLoad(params => {  
  const url = decodeURIComponent(params.url || '')  
  console.debug('webview onLoad. url: ', url)  
  s.url = url  
})  

onBackPress((e: any) => {  
  // #ifdef APP-PLUS  
  if (e.from === 'navigateBack') return false //使用了uni api发起后退事件,不在此处处理  
  //否则,用户按下了物理后退键  
  if (s.canBack) { //webview可后退(history页面数大于1),则使用webview api进行后退  
    s.getAppWebview().back()  
    return true  
  } //否则,webview已没有更多页面可供后退,让框架调用默认的物理后退键功能(提示重复按键退出app)  
  // #endif  
  return false  
})  
</script>

tryGet:

import {delay} from './delay'  

export async function tryGet<T>(getter: () => T, interval: number, maxTimes: number) {  
    for (let i = 0; i < maxTimes; i++) {  
      await delay(interval)  
      const r = await getter()  
      if (r) return r  
    }  
    return undefined  
  }

delay:

export async function delay(ms: number) {  
  return new Promise(resolve => setTimeout(resolve, ms))  
}

react:

import {reactive} from 'vue'  

export function react<T extends object>(block: () => T) {  
  return reactive(block())  
}

该问题目前已经被锁定, 无法添加新回复