简体中文 
 组件类型:UniWebViewElement
承载网页的容器
| Web | 微信小程序 | Android | iOS | HarmonyOS | 
|---|---|---|---|---|
| 4.0 | 4.41 | 3.9 | 4.11 | 4.61 | 
| 名称 | 类型 | 默认值 | 兼容性 | 描述 | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| src | string(string.HTMLURIString) | - | webview 指向网页的链接 | ||||||||||||||||
| allow | string | - | 用于为 iframe 指定其特征策略 | ||||||||||||||||
| sandbox | string | - | 该属性对呈现在 iframe 框架中的内容启用一些额外的限制条件。 | ||||||||||||||||
| fullscreen | boolean | - | 是否铺满整个页面,默认值:true。 | ||||||||||||||||
| webview-styles | WebViewStyles | {"progress":{"color":"#00FF00"}} | webview 网络地址页面加载进度条样式 | ||||||||||||||||
  | |||||||||||||||||||
| horizontalScrollBarAccess | boolean | true | 设置是否显示横向滚动条 | ||||||||||||||||
| verticalScrollBarAccess | boolean | true | 设置是否显示纵向滚动条 | ||||||||||||||||
| bounces | boolean | true | 设置是否开启回弹效果 | ||||||||||||||||
| android-nested-scroll | string | "all" | 设置嵌套滚动方向 | ||||||||||||||||
  | |||||||||||||||||||
| disable-user-select-menu | boolean | false | 设置是否禁用文本选择时弹出的系统菜单 | ||||||||||||||||
| @message | (event: UniWebViewMessageEvent) => void | - | 网页向应用 postMessage 时触发。e.detail = { data } | ||||||||||||||||
| @error | (event: UniWebViewErrorEvent) => void | - | 网页加载错误时触发。e.detail = { errSubject, errCode, errMsg, url, fullUrl, src } | ||||||||||||||||
| @load | (event: UniWebViewLoadEvent) => void | - | 网页加载完成后触发。e.detail = { url, src } | ||||||||||||||||
| @loading | (event: UniWebViewLoadingEvent) => void | - | 网页开始加载时触发。e.detail = { url, src } | ||||||||||||||||
| @download | (event: UniWebViewDownloadEvent) => void | - | 点击网页中可下载链接时触发。e.detail = { url, userAgent, contentDisposition, mimetype, contentLength } | ||||||||||||||||
| @contentheightchange | (event: UniWebViewContentHeightChangeEvent) => void | - | 网页内容高度变化时触发。e.detail = { height } | ||||||||||||||||
| (event: UniWebViewLoadEvent) => void | - | 网页加载完成后触发。e.detail = { url, src }。已废弃,请改用load | |||||||||||||||||
| 名称 | 类型 | 必填 | 默认值 | 兼容性 | 描述 | 
|---|---|---|---|---|---|
| type | string | 是 | - | - | 事件类型,固定值message | 
| 名称 | 类型 | 必填 | 默认值 | 兼容性 | 描述 | 
|---|---|---|---|---|---|
| data | UTSJSONObject[] | 是 | - | - | 消息包含的数据,4.13版本之前类型为Map<string, any | null> | null,4.13版本(含)之后类型为Array<UTSJSONObject> | 
| 名称 | 类型 | 必填 | 默认值 | 兼容性 | 描述 | 
|---|---|---|---|---|---|
| type | string | 是 | - | - | 事件类型,固定值error | 
| 名称 | 类型 | 必填 | 默认值 | 兼容性 | 描述 | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| errSubject | string | 是 | - | - | 统一错误主题(模块)名称,固定值uni-web-view | ||||||||||||
| errCode | number | 是 | - | - | 统一错误码 100001 ssl error 100002 page error 100003 http error  | ||||||||||||
  | |||||||||||||||||
| errMsg | string | 是 | - | - | 统一错误描述信息 | ||||||||||||
| url | string | 是 | - | - | 加载错误的网页链接,非完整链接,仅包含scheme://authority部分,4.13版本起支持 | ||||||||||||
| fullUrl | string | 是 | - | - | 加载错误的网页链接,完整链接,4.13版本起支持 | ||||||||||||
| src | string | 是 | - | - | 加载错误的网页链接,完整链接,4.13版本起支持 | ||||||||||||
| 名称 | 类型 | 必填 | 默认值 | 兼容性 | 描述 | 
|---|---|---|---|---|---|
| type | string | 是 | - | - | 事件类型,固定值load | 
| 名称 | 类型 | 必填 | 默认值 | 兼容性 | 描述 | 
|---|---|---|---|---|---|
| string | 是 | - | - | 加载完成的网页链接 | |
| src | string | 是 | - | - | 加载完成的网页链接,4.13版本起支持 | 
| 名称 | 类型 | 必填 | 默认值 | 兼容性 | 描述 | 
|---|---|---|---|---|---|
| type | string | 是 | - | - | 事件类型,固定值loading | 
| 名称 | 类型 | 必填 | 默认值 | 兼容性 | 描述 | 
|---|---|---|---|---|---|
| string | 是 | - | - | 加载中的网页链接 | |
| src | string | 是 | - | - | 加载中的网页链接,4.13版本起支持 | 
| 名称 | 类型 | 必填 | 默认值 | 兼容性 | 描述 | 
|---|---|---|---|---|---|
| type | string | 是 | - | - | 事件类型,固定值download | 
| 名称 | 类型 | 必填 | 默认值 | 兼容性 | 描述 | 
|---|---|---|---|---|---|
| url | string | 是 | - | - | 下载链接 | 
| userAgent | string | 是 | - | - | 用户代理 | 
| contentDisposition | string | 是 | - | - | 指示回复的内容该以何种形式展示,是以内联的形式(即网页或者页面的一部分),还是以附件的形式下载并保存到本地 | 
| mimetype | string | 是 | - | - | 媒体类型 | 
| contentLength | number | 是 | - | - | 文件大小 | 
| 名称 | 类型 | 必填 | 默认值 | 兼容性 | 描述 | 
|---|---|---|---|---|---|
| type | string | 是 | - | - | 事件类型,固定值contentheightchange | 
| 名称 | 类型 | 必填 | 默认值 | 兼容性 | 描述 | 
|---|---|---|---|---|---|
| height | number | 是 | - | - | 内容高度 | 
App平台 web-view 组件可在 scroll-view、list-view/list-item 等可滚动容器中使用,如果 web-view 中的内容可以滚动,则会出现嵌套滚动的问题,细节如下:
本地路径/static方式 由于uni-app/uni-app x编译时,只把/static目录下的静态资源copy到app中,所以src均需指向/static目录下。 其他目录的html文件由于不会被打包进去,所以无法访问。 app平台文件路径会存在大小写敏感问题,为了有更好的兼容性,建议统一按大小写敏感原则处理 详情
支持网络路径 支持http、https。 app平台使用系统Webview组件,由系统Webview管理缓存。
不可以嵌套组件
示例为hello uni-app x alpha分支,与最新HBuilderX Alpha版同步。与最新正式版同步的master分支示例另见
示例
<template>
  <view class="uni-flex-item">
    <web-view id="web-view" class="uni-flex-item" :style="webViewStyle" :src="src"
      :webview-styles="webview_styles" :horizontalScrollBarAccess="horizontalScrollBarAccess" :verticalScrollBarAccess="verticalScrollBarAccess"
      :bounces="bounces" :disable-user-select-menu="disableUserSelectMenu" @message="message" @error="error" @loading="loading"
      @load="load" @download="download" @contentheightchange="contentheightchange" @touchstart="touchstart" @tap="tap">
    </web-view>
    <!-- #ifdef APP -->
    <view class="uni-padding-wrap uni-common-mt">
      <view class="uni-btn-v">
        <input class="uni-input" confirmType="go" placeholder="输入网址跳转" @confirm="confirm" maxlength="-1" />
      </view>
      <view class="uni-row uni-btn-v">
        <button class="uni-flex-item" type="primary" :disabled="!canGoBack" @click="back">后退</button>
        <button class="margin-left-5 uni-flex-item" type="primary" :disabled="!canGoForward"
          @click="forward">前进</button>
      </view>
      <view class="uni-row uni-btn-v">
        <button class="uni-flex-item" type="primary" @click="reload">重新加载</button>
        <button class="margin-left-5 uni-flex-item" type="primary" @click="stop">停止加载</button>
      </view>
      <view class="uni-row uni-btn-v">
        <button class="uni-flex-item" type="primary" @click="nativeToWeb">原生和Web通信</button>
        <!-- #ifdef APP-ANDROID || APP-IOS || APP-HARMONY -->
        <button class="margin-left-5 uni-flex-item" type="primary" @click="getContentHeight">获取内容高度</button>
        <!-- #endif -->
      </view>
      <view class="uni-row uni-btn-v">
        <button class="uni-flex-item" type="primary" @click="loadData">加载页面内容</button>
        <!-- 用于演示大尺寸平板中能用窄屏展示响应式内容 -->
        <button id="half-screen-toggle" class="margin-left-5 uni-flex-item" type="primary" @click="setHalfScreen">宽窄屏切换</button>
      </view>
      <view class="uni-btn-v">
        <navigator url="/pages/component/web-view/web-view-scroll">
          <button type="primary">scroll-view嵌套web-view</button>
        </navigator>
      </view>
      <!-- #ifdef APP-ANDROID || APP-HARMONY || APP-IOS -->
      <view class="uni-row uni-btn-v">
        <view class="uni-row uni-flex-item align-items-center">
          <text>显示横向滚动条</text>
          <switch :checked="true" @change="changeHorizontalScrollBarAccess"></switch>
        </view>
        <view class="uni-row uni-flex-item align-items-center">
          <text>显示竖向滚动条</text>
          <switch :checked="true" @change="changeVerticalScrollBarAccess"></switch>
        </view>
      </view>
      <view class="uni-row uni-btn-v">
        <view class="uni-row uni-flex-item align-items-center">
          <text>开启bounces</text>
          <switch :checked="true" @change="changeBounces"></switch>
          <!-- #ifdef APP-ANDROID || APP-IOS-->
          <text>禁用选择菜单</text>
          <switch :checked="false" @change="changeDisableUserSelectMenu"></switch>
          <!-- #endif -->
        </view>
      </view>
      <!-- #endif -->
      <!-- #ifdef APP-IOS -->
      <view class="uni-row uni-btn-v" v-if="isProd() === false">
        <view class="uni-row uni-flex-item align-items-center">
          <text>前进、后退功能在Windows端需要打自定义基座,MAC端需要配置Xcode环境后进行真机运行或者打自定义基座</text>
        </view>
      </view>
      <!-- #endif -->
    </view>
    <!-- #endif -->
    <!-- #ifdef APP-ANDROID || APP-IOS -->
    <view class="safe-area-inset-bottom"></view>
    <!-- #endif -->
  </view>
</template>
<script>
  // #ifdef APP
  import { canWebViewGoBack, canWebViewGoForward, hasNativeView } from '@/uni_modules/uts-get-native-view';
  // #endif
  let webviewElement =  null as UniWebViewElement | null
  export default {
    data() {
      return {
        src: 'https://www.dcloud.io',
        webview_styles: {
          progress: {
            color: '#FF3333'
          }
        },
        halfWindowMode:false,
        webviewContext: null as WebviewContext | null,
        loadError: false,
        horizontalScrollBarAccess: true,
        verticalScrollBarAccess: true,
        bounces: true,
        disableUserSelectMenu: false,
        canGoBack: false,
        canGoForward: false,
        // 自动化测试
        autoTest: false,
        eventLoading: null as UTSJSONObject | null,
        eventLoad: null as UTSJSONObject | null,
        eventError: null as UTSJSONObject | null,
        eventContentHeightChange: null as UTSJSONObject | null,
        pointerEvents: 'auto',
        isTouchEnable: false,
        loadingCount: 0
      }
    },
    computed:{
      fullScreen(){
        return !this.halfWindowMode
      },
      webViewStyle(){
        return {
          width: this.halfWindowMode?'50%':'100%',
          'pointer-events': this.pointerEvents
        }
      },
    },
    onReady() {
      // #ifdef APP
      // TODO web 实现createWebviewContext
      // this.webviewContext = uni.createWebviewContext('web-view', this)
      // NOTE 绑定到 this 上会被代理导致无法调用方法
      webviewElement = uni.getElementById('web-view') as UniWebViewElement //推荐使用element,功能更丰富
      // console.log('url: ',this.webviewElement?.getAttribute("src"));
      // this.webviewElement?.setAttribute("src","https://ext.dcloud.net.cn/")
      // #endif
    },
    onUnload() {
      webviewElement = null;
    },
    methods: {
      setHalfScreen(){
        this.halfWindowMode = !this.halfWindowMode
      },
      getPackageName() : string {
        let packageName : string = ""
        // #ifdef APP-IOS
        const res = uni.getAppBaseInfo();
        packageName = res.bundleId
        // #endif
        return packageName
      },
      isProd() : boolean {
        if (this.getPackageName() == 'io.dcloud.hellouniappx') {
          return true
        }
        return false
      },
      back() {
        webviewElement?.back();
      },
      forward() {
        webviewElement?.forward();
      },
      reload() {
        this.loadingCount = 0
        webviewElement?.reload();
      },
      stop() {
        webviewElement?.stop();
      },
      nativeToWeb() {
        webviewElement?.evalJS("alert('hello uni-app x')");
      },
      // #ifdef APP-ANDROID || APP-IOS || APP-HARMONY
      getContentHeight() : number {
        const height = webviewElement?.getContentHeight() ?? 0;
        console.log('contentHeight', height);
        if (!this.autoTest) {
          uni.showModal({
            content: ' 当前内容高度: ' + height,
            showCancel: false
          });
        }
        return height;
      },
      loadData() {
        webviewElement?.loadData({
          data: '<p><a href="https://www.dcloud.io/hbuilderx.html">HBuilderX</a><br/><img src="/unidoc/zh/uni@2x.png"></img><h1>HBuilderX,轻巧、极速,极客编辑器</h1><p style="color:red;"><small>HBuilderX,轻巧、极速,极客编辑器 </small><big>HBuilderX,轻巧、极速,极客编辑器</big><strong>HBuilderX,轻巧、极速,极客编辑器</strong><i>HBuilderX,轻巧、极速,极客编辑器 </i><u>HBuilderX,轻巧、极速,极客编辑器</u><del>HBuilderX,轻巧、极速,极客编辑器</del></p><h2>uni-app x,终极跨平台方案</h2>、<p style="background-color: yellow;"><small>uni-app x,终极跨平台方案 </small><big>uni-app x,终极跨平台方案</big><strong>uni-appx,终极跨平台方案 </strong><i>uni-app x,终极跨平台方案 </i><u>uni-app x,终极跨平台方案 </u><del>uni-appx,终极跨平台方案</del></p><h3>uniCloud,js serverless云服务</h3><p style="text-decoration: line-through;"><small>uniCloud,js serverless云服务 </small><big>uniCloud,jsserverless云服务</big><strong>uniCloud,js serverless云服务 </strong><i>uniCloud,js serverless云服务 </i><u>uniCloud,jsserverless云服务</u><del>uniCloud,js serverless云服务</del></p><h4>uts,大一统语言</h4><p style="text-align: center;"><small>uts,大一统语言 </small><big>uts,大一统语言 </big><strong>uts,大一统语言</strong><i>uts,大一统语言</i><u>uts,大一统语言 </u><del>uts,大一统语言</del></p><h5>uniMPSdk,让你的App具备小程序能力</h5><h6>uni-admin,开源、现成的全端管理后台</h6><ul><li style="color: red; text-align: left;">uni-app x,终极跨平台方案</li><li style="color: green; text-align: center;">uni-app x,终极跨平台方案</li><li style="color: blue; text-align: right;">uni-app x,终极跨平台方案</li></ul><a href="https://uniapp.dcloud.net.cn">uni-app</a><br/><img src="/unidoc/zh/uni@2x.png"></img></p>',
          baseURL: 'https://qiniu-web-assets.dcloud.net.cn'
        });
      },
      // #endif
      message(event : UniWebViewMessageEvent) {
        console.log(JSON.stringify(event.detail));
      },
      error(event : UniWebViewErrorEvent) {
        this.loadError = true
        console.log(JSON.stringify(event.detail));
        if (this.autoTest) {
          this.eventError = {
            "tagName": event.target?.tagName,
            "type": event.type,
            "errCode": event.detail.errCode,
            "errMsg": event.detail.errMsg,
            "url": event.detail.url,
            "fullUrl": event.detail.fullUrl,
            "src": event.detail.src
          };
        }
      },
      loading(event : UniWebViewLoadingEvent) {
        this.loadingCount ++
        console.log(JSON.stringify(event.detail));
        if (this.autoTest) {
          this.eventLoading = {
            "tagName": event.target?.tagName,
            "type": event.type,
            "src": event.detail.src
          };
        }
      },
      load(event : UniWebViewLoadEvent) {
        console.log(JSON.stringify(event.detail));
        // #ifdef APP
        this.canGoBack = canWebViewGoBack('web-view');
        this.canGoForward = canWebViewGoForward('web-view');
        // #endif
        if (this.autoTest) {
          this.eventLoad = {
            "tagName": event.target?.tagName,
            "type": event.type,
            "src": event.detail.src,
            "url": event.detail.url,
          };
        }
      },
      download(event : UniWebViewDownloadEvent) {
        console.log(JSON.stringify(event.detail));
        uni.showModal({
          content: "下载链接: " + event.detail.url + "\n文件大小: " + event.detail.contentLength / 1024 + "KB",
          showCancel: false
        });
      },
      contentheightchange(event : UniWebViewContentHeightChangeEvent) {
        console.log(JSON.stringify(event.detail));
        this.eventContentHeightChange = {
          "tagName": event.target?.tagName,
          "type": event.type,
          "isValidHeight": event.detail.height > 0
        };
      },
      confirm(event : UniInputConfirmEvent) {
        let url = event.detail.value;
        if (!url.startsWith('https://') && !url.startsWith('http://')) {
          url = 'https://' + url;
        }
        this.src = url;
      },
      changeHorizontalScrollBarAccess(event : UniSwitchChangeEvent) {
        this.horizontalScrollBarAccess = event.detail.value;
      },
      changeVerticalScrollBarAccess(event : UniSwitchChangeEvent) {
        this.verticalScrollBarAccess = event.detail.value;
      },
      changeBounces(event : UniSwitchChangeEvent) {
        this.bounces = event.detail.value;
      },
      changeDisableUserSelectMenu(event : UniSwitchChangeEvent) {
        this.disableUserSelectMenu = event.detail.value;
      },
      // 自动化测试
      touchstart(event : UniTouchEvent) {
        if (this.autoTest) {
          this.isTouchEnable = event.touches[0].clientX > 0 && event.touches[0].clientY > 0;
        }
      },
      tap(event : UniPointerEvent) {
        if (this.autoTest) {
          this.isTouchEnable = event.clientX > 0 && event.clientY > 0;
        }
      },
      //自动化测试专用
      checkNativeWebView() : boolean {
        // #ifdef APP
        return hasNativeView('web-view')
        // #endif
        // #ifdef WEB
        return true
        // #endif
      },
      checkLoadingCount() {
        this.loadingCount = 0
        webviewElement?.reload();
      }
    }
  }
</script>
<style>
  .margin-left-5 {
    margin-left: 5px;
  }
  .align-items-center {
    align-items: center;
  }
  .safe-area-inset-bottom {
    height: var(--uni-safe-area-inset-bottom);
  }
</style>
web-view的操作api为uni.createWebviewContext()。
给web-view组件设一个id属性,将id的值传入uni.createWebviewContext(),即可得到web-view组件的上下文对象,进一步可使用.evalJS()、.reload()等封装好的跨平台方法。
为增强uni-app x组件的开放性,从 HBuilderX 4.25 起,UniElement对象提供了 getAndroidView 和 getIOSView 方法。
该方法可以获取到 web-view 组件对应的原生 WebView 对象,从而可以调用原生 API 以扩展当前 web-view 组件和上下文对象未提供的能力。
比如:Android 平台和 iOS 平台的原生 WebView 都提供了 canGoBack 和 canGoForward 两个 API,用来判断当前网页是否可以回退和前进。但 uni-app x 的 web-view 组件上下文对象没有封装上述 API。
下面则举例说明在 Android 平台如何通过获取原生 WebView 对象来实现上述能力(iOS 平台写法类似)。
import WebView from 'android.webkit.WebView';
function canGoBack() : boolean {
	// 第一步获取web-view组件的UniElement对象
	const element = uni.getElementById(elementId); //elementId为页面上web-view组件的id。不过一般建议从uvue页面给uts插件传入指定的UniElement对象,而不是在uts插件中直接获取页面组件的id。
	// 第二步通过UniElement的getAndroidView方法,通过泛型指定的方式,获取Android原生的WebView对象。泛型参数即为原生对象的类型名称
  const webview = element?.getAndroidView<WebView>();
	// 然后就可以调用原生WebView的各种方法,比如 canGoBack 方法
  return webview == null ? false : webview.canGoBack();
}
function canGoForward() : boolean {
  const element = uni.getElementById(elementId); //elementId为页面上web-view组件的id
  const webview = element?.getAndroidView<WebView>();
  return webview == null ? false : webview.canGoForward();
}
详细的示例源码,在 hello uni-app x 的 组件 -> web-view 示例 中, 获取原生WebView对象,然后进一步使用了可否前进后退的方法,封装代码如下:
uts向web-view的网页发消息
使用evalJS()方法,详见上方示例代码
web-view里的网页向uts发消息
在网页中引入uni.webview.1.5.5.js。即可在网页中调用一批uni的api,包括:
| 方法名 | 说明 | 平台差异说明 | 
|---|---|---|
| uni.webView.navigateTo | navigateTo | Web平台暂不支持 | 
| uni.webView.redirectTo | redirectTo | Web平台暂不支持 | 
| uni.webView.reLaunch | reLaunch | Web平台暂不支持 | 
| uni.webView.switchTab | switchTab | Web平台暂不支持 | 
| uni.webView.navigateBack | navigateBack | Web平台暂不支持 | 
| uni.webView.getEnv | 获取当前webView环境 | uvue/nvue/plus/h5 | 
| uni.webView.postMessage | 向应用发送消息 | Web平台暂不支持 | 
在网页中使用uni.webView.postMessage()即可向uts发送消息。
uts端在 <web-view> 组件的 message 事件回调 event.detail.data 中接收消息。
示例代码详见hello uni-app x 的 /hybrid/html/local.html
Tips
event.detail.data 中的数据,以数组的形式接收每次 post 的消息。(注:支付宝小程序除外,支付宝小程序中以对象形式接受)web-view组件有跨域问题,服务器网页的跨域问题属于常规web开发范畴,请自行查阅文档。
但当App平台加载本地磁盘的html文件时,跨域问题需要单独说明。
各App平台的webview对本地网页跨域的策略不同,Android、iOS、鸿蒙,要求依次严格。
鸿蒙其自身有设计问题,在同一时间,web-view只能配置允许访问下列2种本地目录中的一种。
uni-app x中,web-view组件在鸿蒙上默认配置为允许跨域访问 App包资源。
所以,默认情况下,web-view访问应用沙盒文件会报不允许访问。
// 获取web-view组件对应的鸿蒙原生Controller
const webviewController = uni.getElementById(elementId)?.getHarmonyController() as webview.WebviewController | null
// 修改跨域设置
webviewController?.setPathAllowingUniversalAccess([])
const webviewController = uni.getElementById(elementId)?.getHarmonyController() as webview.WebviewController | null
webviewController?.setPathAllowingUniversalAccess([
	getContext()!.filesDir,
	getContext()!.getApplicationContext().filesDir,
	getContext()!.resourceDir,
	getContext()!.getApplicationContext().resourceDir
].filter(item => !!item).map(item => item + '/uni-app-x/apps'))
鸿蒙的安全团队认为过多开放目录访问会造成安全漏洞,但同时也限制了开发者需求的实现。DCloud正在与华为交涉,详见