HarmonyOS鸿蒙Next中web组件如何加载Html内容

HarmonyOS鸿蒙Next中web组件如何加载Html内容 Web组件如何加载html内容,是后端返回的html的内容,不是URL。

其中,html里面有类似的图片加载

9 回复

cke_138.png

import { webview } from '@kit.ArkWeb';

@Entry
@Component
struct WebContent {
  controller: webview.WebviewController = new webview.WebviewController();
  @State htmlContent: string = `
    <html>
      <body>
        <h1>后端返回的HTML内容</h1>

      </body>
    </html>
  `;

  build() {
    Column() {
      Web({ src: '', controller: this.controller })
        .onControllerAttached(() => {
          // 方式1:使用loadData(需编码)
          this.controller.loadData(
            encodeURIComponent(this.htmlContent),
            "text/html",
            "UTF-8"
          );

          // 方式2:使用loadHtml(API 9+,无需编码)
          // this.controller.loadHtml(this.htmlContent);
        })
    }
  }
}

更多关于HarmonyOS鸿蒙Next中web组件如何加载Html内容的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在鸿蒙里,Web 组件本身 没有“直接塞字符串”的 props,但官方在 WebviewController 上提供了两个等价接口,可以把后端返回的 HTML 字符串 立即渲染出来,而不用落地成文件。任选其一即可,推荐 loadData(),代码最少、最直观。

一、最快方案 —— loadData()

import { webview } from '@kit.ArkWeb';

@Entry
@Component
struct HtmlStringPage {
  ctrl = new webview.WebviewController();
  @State html: string = ''; // 后端返回的完整 html

  aboutToAppear() {
    // 模拟后台返回
    this.html = `
      <html>
        <body>
          <h1>标题</h1>
          <img src="https://www.example.com/a.jpg" />
        </body>
      </html>`;
  }

  build() {
    Column() {
      Button('加载 HTML 字符串')
        .onClick(() => {
          // 第四个参数 baseUrl 可留空;图片里的 https 会自动走网络
          this.ctrl.loadData(this.html, 'text/html', 'UTF-8');
        })
      Web({ src: '', controller: this.ctrl }) // src 先留空
        .layoutWeight(1)
    }
  }
}
  1. 不用事先写文件,loadData 直接把字符串写进 Web 内核。
  2. 如果 html 里引用了 https:// 图片,只要设备能访问外网就能正常加载;纯内网就把图片地址换成内网地址即可。
  3. 字符串很大时,把第 4 个参数 baseUrl 设成 ‘data://’ 可提升解析速度 。

loadData

loadData(data: string, mimeType: string, encoding: string, baseUrl?: string, historyUrl?: string): void

加载指定的数据。

baseUrl与historyUrl同时为空的情况下:

encoding如果为非base64(包括空值),则假定数据对安全URL字符范围内的八位字节使用ASCII编码,对该范围外的八位字节使用URL的标准%xx十六进制编码。

data数据必须使用base64编码或将内容中的任何#字符编码为%23。否则#将被视为内容的结尾而剩余的文本将被用作文档片段标识符。

说明

  • 若加载本地图片,可以给baseUrl或historyUrl任一参数赋值空格,详情请参考示例代码。
  • 加载本地图片场景,baseUrl和historyUrl不能同时为空,否则图片无法成功加载。
  • 若html中的富文本中带有注入#等特殊字符,建议将baseUrl和historyUrl两个参数的值设置为"空格"。
  • 加载文字场景,需主动设置<meta name="viewport" content="width=device-width, initial-scale=1.0" charset="utf-8">避免文本字体大小不一致。

系统能力: SystemCapability.Web.Webview.Core

参数:

参数名 类型 必填 说明
data string 按照"base64"或者"URL"编码后的一段字符串。
mimeType string 媒体类型(MIME)。
encoding string 编码类型,具体为"base64"或者"URL"编码。
baseUrl string 指定的一个URL路径(“http”/“https”/“data"协议),并由Web组件赋值给window.origin。当加载大量html文件时,需设置为"data”。
historyUrl string 用作历史记录所使用的URL。非空时,历史记录以此URL进行管理。当baseUrl为空时,此属性无效。

错误码:

以下错误码的详细介绍请参见Webview错误码通用错误码

错误码ID 错误信息
17100001 Init error. The WebviewController must be associated with a Web component.
401 Parameter error. Possible causes: 1. Mandatory parameters are left unspecified. 2. Incorrect parameter types. 3.Parameter verification failed.

示例:

baseUrl与historyUrl同时为空。

// xxx.ets
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct WebComponent {
  controller: webview.WebviewController = new webview.WebviewController();
  build() {
    Column() {
      Button('loadData')
        .onClick(() => {
          try {
            this.controller.loadData(
              "<html><body bgcolor=\"white\">Source:<pre>source</pre></body></html>",
              "text/html",
              // UTF-8为charset。
              "UTF-8"
            );
          } catch (error) {
            console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
          }
        })
      Web({ src: 'www.example.com', controller: this.controller })
    }
  }
}
// xxx.ets
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct WebComponent {
  controller: webview.WebviewController = new webview.WebviewController();
  build() {
    Column() {
      Button('loadData')
        .onClick(() => {
          try {
            this.controller.loadData(
              // Coding tests通过base64编码后的字符串。
              "Q29kaW5nIHRlc3Rz",
              "text/html",
              "base64"
            );
          } catch (error) {
            console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
          }
        })
      Web({ src: 'www.example.com', controller: this.controller })
    }
  }
}

静静地静静地觉得好的话好多好多好多好多好多的话

我不太明白,为什么上面的html无法加载出来,但是我把span里面的样式style="color:#636366;font-size:14px;background-color:#FFFFFF;"去掉后又可以加载出来,这到底是什么原因?

是特殊字符哦!

loadData使用不同的参数会有不同的效果,如果参数不对可能会造成白屏现象。如果html中存在非法字符,例如css中的color: “#333”,有"#"的时候会加载不了,建议将baseUrl和historyUrl两个参数的值设置为"空格"即可解决问题。

web组件加载HTML格式的文本数据

1、Web组件可以通过loadData()接口实现加载HTML格式的文本数据。

当开发者不需要加载整个页面,只需要显示一些页面片段时,可通过此功能来快速加载页面,当加载大量html文件时,需设置第四个参数baseUrl为"data"。

// xxx.ets
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
@Component
struct WebComponent {
  controller: webview.WebviewController = new webview.WebviewController();

  build() {
    Column() {
      Button('loadData')
        .onClick(() => {
          try {
            // 点击按钮时,通过loadData,加载HTML格式的文本数据
            this.controller.loadData(
              "<html><body bgcolor=\"white\">Source:<pre>source</pre></body></html>",
              "text/html",
              "UTF-8"
            );
          } catch (error) {
            console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
          }
        })
      // 组件创建时,加载www.example.com
      Web({ src: 'www.example.com', controller: this.controller })
    }
  }
}

2、Web组件可以通过data url方式直接加载HTML字符串。

// xxx.ets
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
@Component
struct WebComponent {
  controller: webview.WebviewController = new webview.WebviewController();
  htmlStr: string = "data:text/html, <html><body bgcolor=\"white\">Source:<pre>source</pre></body></html>";

  build() {
    Column() {
      // 组件创建时,加载htmlStr
      Web({ src: this.htmlStr, controller: this.controller })
    }
  }
}

静静地静静地觉得好的话好多好多好多好多好多的话

我不太明白,为什么上面的html无法加载出来,但是我把span里面的样式style="color:#636366;font-size:14px;background-color:#FFFFFF;"去掉后又可以加载出来,这到底是什么原因?

在HarmonyOS Next中,使用Web组件加载HTML内容主要通过loadData()方法实现。该方法允许直接加载HTML字符串,并支持设置MIME类型和编码。

示例代码:

webview.loadData(
    "<html><body><h1>Hello HarmonyOS</h1></body></html>",
    "text/html",
    "UTF-8"
);

也可以使用loadUrl()加载本地或远程HTML文件。需注意配置网络权限和本地文件访问权限。

在HarmonyOS Next中,使用Web组件加载后端返回的HTML字符串内容,而不是通过URL,可以通过设置Web组件的htmlText属性来实现。

核心方法:使用 htmlText 属性

  1. 基本加载:将获取到的后端HTML字符串直接赋值给Web组件的htmlText属性即可完成加载。

    // 假设 htmlContent 是从后端获取到的HTML字符串
    let htmlContent: string = '<p>后端返回的HTML内容</p><img src="https://example.com/image.jpg">';
    
    build() {
      Column() {
        // 使用 htmlText 属性加载HTML字符串
        Web({ src: $rawfile('about:blank'), controller: this.controller })
          .width('100%')
          .height('100%')
          .onPageEnd(() => {
            // 页面加载完成后,通过执行JavaScript设置HTML内容
            this.controller.runJavaScript({
              script: `document.write('${htmlContent}');`,
              callback: (result) => {
                // 处理回调
              }
            });
          })
      }
    }
    

    注意:更直接的方式是在构建Web组件时,如果已经获取到htmlContent,可以直接在src中构造一个Data URL,但使用onPageEnd回调配合runJavaScript是动态加载内容的常用方式。

  2. 处理图片等网络资源:当HTML中包含类似<img src="https://...">的网络图片时,只要设备可以正常访问该URL,Web组件会像普通浏览器一样自动加载并显示这些图片,无需特殊处理。确保应用已申请必要的网络权限(ohos.permission.INTERNET)。

关键点说明:

  • htmlText vs srchtmlText属性专门用于直接加载HTML字符串内容。如果内容在应用启动时已确定,使用htmlText更直接。上述示例中使用的onPageEndrunJavaScript方法适用于需要先加载一个空白页面再动态注入HTML内容的场景。
  • 网络图片:图片能否正常显示取决于网络连通性和图片服务器可达性。Web组件内部会处理网络资源的加载。
  • 性能与安全:对于大段HTML内容,直接使用htmlTextrunJavaScript是高效的。但需注意,注入的HTML/JavaScript代码应来自可信源,以防XSS等安全风险。
  • 样式与交互:加载的HTML内容中的CSS样式和JavaScript脚本(如果有)在Web组件中同样会生效并执行,这允许你展示富文本或交互式内容。

示例代码片段(直接使用htmlText的简化版):

// 构建Web组件时直接传入HTML字符串
Web({ htmlText: this.htmlContent, controller: this.controller })
  .width('100%')
  .height('100%')

这种方式适用于在构建时内容已就绪的情况。

总结,加载后端返回的HTML字符串到Web组件,核心是使用htmlText属性或通过runJavaScript方法动态写入document。其中的网络图片会自动加载,只要确保网络权限和连接正常即可。

回到顶部