引言

在移动应用开发中,WebView 是一个极为重要的组件。无论是展示帮助文档、加载在线内容、嵌入H5页面,还是构建完整的应用内浏览器,都离不开 WebView 的支持。HarmonyOS NEXT 提供了功能强大的 Web 组件,它不仅支持基本的网页加载与渲染,还提供了丰富的 JavaScript 交互、页面导航控制、加载状态监听、混合内容处理等高级能力。

本文将通过构建一个功能完整的"轻量浏览器"应用,深入解析 Web 组件的各项能力。我们将从基础的页面加载开始,逐步实现 URL 输入、导航控制(前进/后退/刷新)、加载进度条、页面标题获取、书签管理等功能。读完本文,你将系统掌握 Web 组件在实际项目中的使用方式。

Web 组件概述

Web 组件是 ArkUI 提供的用于加载和显示网页内容的容器组件。它基于 Chromium 内核,提供了高性能的网页渲染能力。在 HarmonyOS NEXT 中,Web 组件被封装为一个声明式 UI 组件,开发者可以像使用 Text、Button 等组件一样在 build 方法中使用它。

最简用法

Web 组件的最基本用法只需指定两个参数:

Web({ src: 'https://www.example.com', controller: this.controller })
  • src:要加载的网页 URL 字符串
  • controller:WebviewController 控制器对象,用于在代码中控制页面的导航行为

WebviewController 是操作 Web 组件的核心接口。通过它,你可以控制页面的前进、后退、刷新,注入 JavaScript 代码,以及访问页面的历史记录等。

核心能力一览

Web 组件提供了丰富的配置选项和事件回调:

类别 能力 说明
页面控制 loadUrl, refresh, backward, forward 导航操作
JavaScript javaScriptAccess 控制 JS 执行权限
存储 domStorageAccess 控制 DOM Storage 访问
缩放 overviewModeAccess 页面缩放与概览模式
文件 fileAccess 本地文件系统访问
图片 onlineImageAccess 在线图片加载控制
混合内容 mixedMode HTTP/HTTPS 混合内容策略
进度回调 onProgressChange 页面加载进度(0-100)
生命周期 onPageBegin, onPageEnd 页面加载开始/结束
标题回调 onTitleReceive 获取网页标题
错误回调 onErrorReceive 加载错误处理

Demo:轻量浏览器

接下来,我们构建一个功能完备的应用内浏览器。它具备以下功能:

  1. URL 输入与加载
  2. 前进/后退/刷新导航
  3. 加载进度条
  4. 页面标题显示
  5. 常用网址快速访问
  6. 书签收藏与管理

页面整体结构

页面采用垂直三段式布局:

┌──────────────────────────────┐
│  🌐 轻量浏览器    ⭐  🏠    │  ← 顶部栏(深色背景)
│  Web 组件深度体验           │
├──────────────────────────────┤
│  [URL 输入框...]    [前往]  │  ← 工具栏(白色背景)
│  [━━━━━━━━━━━━━━━━━━━━]     │  ← 加载进度条(仅加载时显示)
│  [←] [→] [↻] 页面标题  [☆] │  ← 导航栏
├──────────────────────────────┤
│                              │
│     Web 组件渲染区域        │  ← WebView 主体
│                              │
│  ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐  │  ← 遮罩层(快速链接/书签)
│  │  🔗 常用网址           │  │
│  │  HarmonyOS 开发者       │  │
│  │  鸿蒙开发者论坛         │  │
│  └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘  │
└──────────────────────────────┘

WebviewController 的导入

在 HarmonyOS NEXT 中,WebviewController 通过 @ohos.web.webview 模块引入:

import webview from '@ohos.web.webview';

需要注意的是,这里使用的是默认导入import webview from)而非命名导入(import { webview } from)。这是 HarmonyOS 模块系统的一个特点——@ohos.web.webview 导出的是一个默认的命名空间对象,需要通过 webview.WebviewController 来访问控制器类。

状态变量设计

@State urlInput: string = 'https://developer.huawei.com/consumer/cn/';
@State currentUrl: string = '';
@State pageTitle: string = '加载中...';
@State progressValue: number = 0;
@State isLoading: boolean = false;
@State canGoBack: boolean = false;
@State canGoForward: boolean = false;
@State bookmarks: Bookmark[] = [];
@State showBookmarks: boolean = false;
@State showQuickLinks: boolean = true;
controller: webview.WebviewController = new webview.WebviewController();

这里设计了9个状态变量和一个控制器对象:

  • urlInput:URL 输入框的当前文本,与 TextInput 双向绑定
  • currentUrl:当前实际加载的 URL,用于 Web 组件的 src 参数和书签判断
  • pageTitle:从 Web 组件获取的页面标题
  • progressValue:加载进度,0-100,驱动进度条显示
  • isLoading:是否正在加载中,控制进度条的显隐
  • canGoBack / canGoForward:是否可以后退/前进,控制导航按钮的启用状态
  • bookmarks:书签列表
  • showBookmarks / showQuickLinks:控制遮罩层的显示状态
  • controller:WebviewController 实例,是操作 Web 组件的核心

WebviewController 不是 @State 变量——它是一个控制器对象,不需要响应式更新。但它必须在组件的生命周期内保持引用,以便在按钮点击等事件中调用其方法。
在这里插入图片描述

URL 加载与自动补全

当用户点击"前往"按钮时,我们执行以下逻辑:

handleGo() {
  let url = this.urlInput.trim();
  if (!url) {
    return;
  }
  if (!url.startsWith('http://') && !url.startsWith('https://')) {
    url = 'https://' + url;
    this.urlInput = url;
  }
  this.loadUrl(url);
}

loadUrl(url: string) {
  this.urlInput = url;
  this.currentUrl = url;
  this.showQuickLinks = false;
  this.showBookmarks = false;
  this.controller.loadUrl(url);
}

handleGo 做了两件事:

  1. 空值校验:如果输入为空则直接返回,不做任何操作
  2. 自动补全协议:如果用户输入的是"developer.huawei.com"而非完整的 URL,自动补充 https:// 前缀

loadUrl 是实际执行加载的方法,它:

  1. 同步 URL 输入框和当前 URL 状态
  2. 关闭快速链接和书签遮罩层(让用户看到网页内容)
  3. 调用 controller.loadUrl(url) 触发 Web 组件的页面加载
    在这里插入图片描述

Web 组件的配置与事件

这是整个 Demo 最核心的部分——Web 组件的声明与配置:

Web({ src: this.currentUrl, controller: this.controller })
  .width('100%')
  .height('100%')
  .javaScriptAccess(true)
  .domStorageAccess(true)
  .overviewModeAccess(true)
  .fileAccess(true)
  .onlineImageAccess(true)
  .mixedMode(MixedMode.All)
  .onProgressChange((event) => {
    if (event) {
      this.progressValue = event.newProgress;
    }
  })
  .onPageBegin(() => {
    this.isLoading = true;
    this.progressValue = 0;
  })
  .onPageEnd(() => {
    this.isLoading = false;
    this.progressValue = 100;
  })
  .onTitleReceive((event) => {
    if (event && event.title) {
      this.pageTitle = event.title;
    }
  })

核心配置项解析

javaScriptAccess(true):启用 JavaScript 执行。这是默认开启的,但显式声明是一个好习惯。如果出于安全考虑,可以设置为 false 来禁用 JS。禁用后,网页中的脚本将不会执行,XSS 攻击的风险会降低,但许多现代网站将无法正常工作。

domStorageAccess(true):启用 DOM Storage(包括 localStorage 和 sessionStorage)访问。很多网站依赖 localStorage 存储用户偏好、登录状态等数据,关闭此选项会导致这些功能异常。

overviewModeAccess(true):启用概览模式。这个选项允许网页在加载时自动缩放以适配屏幕宽度,对于移动端未做响应式适配的桌面网站尤为有用。

fileAccess(true):允许 Web 组件访问本地文件系统。如果你的 Web 内容需要加载本地 HTML 文件或资源,必须开启此选项。

onlineImageAccess(true):允许加载在线图片资源。在大多数浏览器场景中都应开启,除非你构建的是一个纯文本浏览器。

mixedMode(MixedMode.All):设置混合内容模式。MixedMode.All 允许在 HTTPS 页面中加载 HTTP 资源。在现代 Web 中,浏览器默认会阻止 HTTPS 页面加载 HTTP 资源(混合内容),但对于某些老旧网站,开启此选项可以避免资源加载失败。
在这里插入图片描述

事件回调解析

onProgressChange:页面加载进度变化时触发。event.newProgress 的值从 0 到 100,代表页面加载的百分比。这个回调在加载过程中会被多次调用,频率取决于页面资源的多少。我们用它来驱动一个线性进度条,给用户直观的加载反馈。

onPageBegin:页面开始加载时触发。我们在这里将 isLoading 设为 true,进度重置为 0。这是展示加载状态的起点。

onPageEnd:页面加载完成时触发。我们将 isLoading 设为 false,进度设为 100。注意:onPageEnd 不代表所有资源都已加载完成(如图片懒加载),但页面主体已经可用。

onTitleReceive:当 Web 组件获取到页面标题时触发。event.title 就是 HTML 中 <title> 标签的内容。我们在导航栏中展示这个标题,让用户知道当前页面的名称。

导航控制

浏览器的核心操作——前进、后退、刷新——通过 WebviewController 的方法实现:

Button() { Text('←').fontSize(16) }
  .backgroundColor(this.canGoBack ? AppColors.PRIMARY : '#E0E0E0')
  .enabled(this.canGoBack)
  .onClick(() => { this.controller.backward(); })

Button() { Text('→').fontSize(16) }
  .backgroundColor(this.canGoForward ? AppColors.PRIMARY : '#E0E0E0')
  .enabled(this.canGoForward)
  .onClick(() => { this.controller.forward(); })

Button() { Text('↻').fontSize(16) }
  .backgroundColor(AppColors.PRIMARY)
  .onClick(() => { this.controller.refresh(); })

三个按钮分别对应 WebviewController 的三个方法:

  • backward():后退到上一个页面,相当于浏览器的"后退"按钮
  • forward():前进到下一个页面,相当于浏览器的"前进"按钮
  • refresh():刷新当前页面,相当于浏览器的"刷新"按钮

一个重要的 UX 细节:后退和前进按钮根据 canGoBackcanGoForward 状态动态控制启用/禁用和颜色。当没有可后退的历史记录时,后退按钮变为灰色且不可点击;有历史记录时才显示主题色。这种视觉反馈让用户清楚地知道当前可以执行哪些操作。

canGoBackcanGoForward 的状态可以通过 WebviewController 的 accessBackward()accessForward() 方法异步获取。在实际生产代码中,你应该在 onPageEnd 回调中主动查询这两个状态:

.onPageEnd(() => {
  this.isLoading = false;
  this.progressValue = 100;
  this.canGoBack = this.controller.accessBackward();
  this.canGoForward = this.controller.accessForward();
})

加载进度条

进度条是一个极好的 UX 细节。在移动端浏览器中,页面加载可能需要数秒时间,如果没有进度指示,用户可能会觉得应用"卡住了":

if (this.isLoading) {
  Progress({ value: this.progressValue, total: 100, type: ProgressType.Linear })
    .width('100%')
    .height(3)
    .color('#1677FF')
    .backgroundColor('#E8F0FE')
    .margin({ top: Spacing.SM })
}

关键设计细节:

  1. 条件渲染:进度条仅在 isLoadingtrue 时才显示。加载完成后,进度条消失,给 Web 内容让出空间
  2. 细条设计:高度仅为 3vp,不占用太多垂直空间,类似 Chrome 浏览器的进度条风格
  3. 色彩搭配:进度色 #1677FF(主题蓝)+ 背景色 #E8F0FE(浅蓝),与整体 UI 色调一致
  4. 缓动效果:由于 onProgressChange 会频繁更新 progressValue,ArkUI 的声明式更新机制会自动产生平滑的进度条动画效果

快速链接面板

首次进入页面时,Web 组件上方展示一个半透明遮罩层,内含常用网址的快速入口:

if (this.showQuickLinks && !this.showBookmarks) {
  Column() {
    Column() {
      Text('🔗 常用网址')
        .fontSize(FontSize.BODY)
        .fontColor(AppColors.TEXT_PRIMARY)
        .fontWeight(FontWeight.Medium)
        .margin({ bottom: Spacing.MD })

      ForEach(QUICK_LINKS, (link: Bookmark) => {
        Row() {
          Text(link.title)
            .fontSize(FontSize.BODY)
            .fontColor('#1677FF')
            .layoutWeight(1)
          Text(link.url)
            .fontSize(FontSize.CAPTION)
            .fontColor(AppColors.TEXT_TERTIARY)
            .maxLines(1)
            .textOverflow({ overflow: TextOverflow.Ellipsis })
            .width(180)
        }
        .width('100%')
        .height(40)
        .padding({ left: Spacing.MD, right: Spacing.MD })
        .backgroundColor('#F8FAFF')
        .borderRadius(BorderRadius.SM)
        .margin({ bottom: Spacing.SM })
        .onClick(() => { this.loadUrl(link.url); })
      })
    }
    .width('80%')
    .padding(Spacing.LG)
    .backgroundColor(Color.White)
    .borderRadius(BorderRadius.MD)
    .shadow({ radius: 20, color: '#00000015', offsetX: 0, offsetY: 4 })
  }
  .width('100%')
  .height('100%')
  .justifyContent(FlexAlign.Center)
  .backgroundColor('#00000030')
  .onClick(() => { this.showQuickLinks = false; })
}

快速链接面板的实现利用了 Stack 组件的层叠特性:

  • 外层 Column:全屏遮罩,半透明黑色背景(#00000030),点击任意空白区域即可关闭面板
  • 内层 Column:白色卡片,80%宽度,居中显示,带有阴影效果。每条链接是一个可点击的 Row,包含标题和 URL

点击链接时调用 loadUrl,它会自动关闭快速链接面板并加载目标网址。

书签管理

书签功能包括三个部分:添加书签、查看书签列表、删除书签。

数据模型

class Bookmark {
  title: string;
  url: string;

  constructor(title: string, url: string) {
    this.title = title;
    this.url = url;
  }
}

书签模型非常简洁,只有标题和 URL 两个字段。标题取自 Web 组件的 onTitleReceive 回调获取的页面标题,URL 是当前加载的地址。

添加书签

addBookmark() {
  const exists = this.bookmarks.some((b: Bookmark) => b.url === this.currentUrl);
  if (!exists && this.currentUrl) {
    this.bookmarks = [...this.bookmarks,
      new Bookmark(this.pageTitle || this.currentUrl, this.currentUrl)];
  }
}

添加书签时做了两个校验:

  1. 去重检查:通过 some() 检查是否已存在相同 URL 的书签,避免重复添加
  2. 空值保护:确保 currentUrl 有效后才添加

书签标题优先使用 pageTitle(网页的 <title>),如果获取不到则降级为 URL。

删除书签

removeBookmark(url: string) {
  this.bookmarks = this.bookmarks.filter((b: Bookmark) => b.url !== url);
}

使用 filter() 创建一个不包含指定 URL 的新数组。注意这里使用了不可变更新模式(创建新数组而非直接修改),这是 ArkUI 中 @State 变量的标准操作方式——只有赋值新对象才能触发状态更新和 UI 重新渲染。

书签面板

书签面板与快速链接面板采用类似的遮罩设计,但在列表项中增加了删除按钮:

ForEach(this.bookmarks, (bk: Bookmark) => {
  Row() {
    Column() {
      Text(bk.title)
        .fontSize(FontSize.BODY)
        .fontColor(AppColors.TEXT_PRIMARY)
        .maxLines(1)
        .textOverflow({ overflow: TextOverflow.Ellipsis })
      Text(bk.url)
        .fontSize(11)
        .fontColor(AppColors.TEXT_TERTIARY)
        .maxLines(1)
        .textOverflow({ overflow: TextOverflow.Ellipsis })
        .margin({ top: 1 })
    }
    .layoutWeight(1)

    Button('✕')
      .fontSize(11)
      .width(28).height(28)
      .backgroundColor('#FFE0E0')
      .fontColor('#FF4D4F')
      .borderRadius(14)
      .onClick(() => { this.removeBookmark(bk.url); })
  }
  .width('100%')
  .padding({ left: Spacing.MD, right: Spacing.SM, top: Spacing.SM, bottom: Spacing.SM })
  .border({ width: { bottom: 1 }, color: '#F5F6FA' })
  .onClick(() => { this.loadUrl(bk.url); this.showBookmarks = false; })
})

书签列表的每个条目有两处点击区域:

  • 条目主体(点击 → 加载该书签 URL 并关闭面板)
  • 删除按钮(点击 → 从书签列表中移除,不会加载 URL)

空状态处理:当书签列表为空时,显示"暂无书签"提示:

if (this.bookmarks.length === 0) {
  Text('暂无书签')
    .fontSize(FontSize.CAPTION)
    .fontColor(AppColors.TEXT_TERTIARY)
    .width('100%')
    .textAlign(TextAlign.Center)
    .padding({ top: Spacing.XL, bottom: Spacing.XL })
}

书签收藏按钮的状态同步

导航栏中的收藏按钮需要实时反映当前页面是否已被收藏:

Button() { Text(this.isBookmarked() ? '⭐' : '☆').fontSize(16) }
  .width(36).height(36)
  .backgroundColor(this.isBookmarked() ? '#FAAD14' : '#F5F6FA')
  .borderRadius(18)
  .onClick(() => {
    if (this.isBookmarked()) {
      this.removeBookmark(this.currentUrl);
    } else {
      this.addBookmark();
    }
  })

isBookmarked(): boolean {
  return this.bookmarks.some((b: Bookmark) => b.url === this.currentUrl);
}

按钮的状态由 isBookmarked() 方法驱动:

  • 未收藏:显示空心星 ☆,底色为浅灰 #F5F6FA
  • 已收藏:显示实心星 ⭐,底色变为金色 #FAAD14

点击收藏按钮时有两种行为:

  • 如果当前页面已收藏 → 取消收藏(删除该书签)
  • 如果当前页面未收藏 → 添加收藏

这种"toggle"模式非常直观,符合用户的心智模型。

URL 输入栏设计

TextInput({ text: this.urlInput, placeholder: '输入网址...' })
  .fontSize(13)
  .height(38)
  .layoutWeight(1)
  .backgroundColor('#F5F6FA')
  .borderRadius(19)
  .padding({ left: 14, right: 14 })
  .onChange((value: string) => { this.urlInput = value; })
  .onSubmit(() => { this.handleGo(); })

设计亮点:

  1. 全圆角胶囊形状borderRadius(19) 配合 height(38),形成 19px 半高的圆角,类似 iOS Safari 的 URL 栏风格
  2. 浅灰背景#F5F6FA 与白色工具栏形成微妙的层次区分
  3. onSubmit 支持键盘"前往":用户可以通过键盘上的确认键触发导航,提升输入效率
  4. 右侧"前往"按钮:蓝色胶囊按钮,提供明确的行动号召

Stack 遮罩层的巧妙运用

快速链接面板和书签面板都使用了 Stack 遮罩层的设计模式:

Stack() {
  Web({ ... })  // 底层:Web 组件

  if (this.showQuickLinks && !this.showBookmarks) {
    Column() {  // 上层:半透明遮罩 + 白色卡片
      ...
    }
    .onClick(() => { this.showQuickLinks = false; })
  }
}
.layoutWeight(1)

这种设计模式有两个优势:

  1. 不遮挡 Web 渲染:面板显示在 Web 组件之上,但 Web 组件仍然在后台保持渲染状态(已加载的页面不会丢失)
  2. 点击空白关闭:外层遮罩的 onClick 事件让用户可以通过点击任意空白区域来关闭面板,这是一种非常自然的移动端交互模式

交互流程

让我们梳理一下用户使用浏览器的典型操作路径:

  1. 首次进入:Web 组件开始加载预设的 HarmonyOS 开发者官网,同时快速链接面板显示在遮罩层上
  2. 点击快速链接:遮罩层关闭,加载对应网址,进度条显示加载状态
  3. 浏览网页:用户在 Web 组件中浏览网页内容,标题实时更新在导航栏中
  4. 点击收藏:当前页面被添加到书签列表,收藏按钮变为金色实心星
  5. 输入URL导航:用户在 URL 栏输入新地址,点击"前往",开始加载新页面
  6. 后退操作:点击后退按钮回到上一个页面(后退按钮在有历史记录时才可点击)
  7. 查看书签:点击顶部 ⭐ 按钮打开书签面板,查看或管理已收藏的网址
  8. 回到首页:点击 🏠 按钮,加载预设的默认网址

这8个操作覆盖了浏览器的主要使用场景,每个操作都对应明确的 UI 反馈。

Web 组件的高级配置

除了 Demo 中已经使用的配置项,Web 组件还支持许多高级功能:

1. 自定义 UserAgent

Web({ src: $url, controller: $controller })
  .userAgent('MyBrowser/1.0 HarmonyOS')

通过设置自定义的 UserAgent,网站可以识别你的应用,并提供适配的页面版本。

2. 注入 JavaScript 代码

this.controller.runJavaScript(`
  document.body.style.backgroundColor = '#f0f0f0';
`);

runJavaScript 方法允许你在 Web 组件中执行任意 JavaScript 代码。这个方法返回一个 Promise,异步获取 JS 执行结果。常见的用途包括修改页面样式、获取页面数据、实现 Web 与 ArkUI 的双向通信。

3. 拦截 URL 请求

Web({ src: $url, controller: $controller })
  .onUrlLoadIntercept((event) => {
    if (event.data.toString().startsWith('app://')) {
      // 拦截自定义 scheme,执行原生逻辑
      return true; // true 表示拦截,不加载
    }
    return false; // false 表示不拦截,正常加载
  })

URL 拦截是实现 Web-Native 通信的重要方式。你可以定义自定义的 URL Scheme(如 app://share?title=xxx),在 onUrlLoadIntercept 回调中拦截这些请求并执行原生操作。

4. 处理下载任务

Web({ src: $url, controller: $controller })
  .onDownloadStart((event) => {
    // event.url 是下载链接
    // event.userAgent 包含 User-Agent 信息
    // 可以调用系统下载管理器处理
  })

当用户点击网页中的下载链接时,这个回调会被触发。你可以在这里接入系统的下载管理器进行处理。

5. SSL 证书错误处理

Web({ src: $url, controller: $controller })
  .onSslErrorEvent((event) => {
    // event.error 包含错误码
    // event.url 是出错的 URL
    // 可以选择是否忽略证书错误继续加载
  })

在访问自签名证书网站或证书有问题时,提供自定义的错误处理逻辑。

6. 设置缓存模式

Web({ src: $url, controller: $controller })
  .cacheMode(CacheMode.Default)

CacheMode 支持多种缓存策略:Default(默认缓存策略)、None(不使用缓存)、Only(仅使用缓存)和 Force(强制使用缓存)。

性能与安全考量

性能优化

  1. 延迟加载:如果 Web 组件不在首屏(比如在 Tab 的第二个页面中),考虑使用条件渲染,在需要时才创建 Web 组件实例。Web 组件的初始化开销较大,延迟加载可以加快应用启动速度

  2. 缓存策略:对于变化不频繁的内容(如帮助文档),设置合适的缓存策略,减少重复加载

  3. 资源限制:避免同时创建多个 Web 组件实例(如在一个长 List 中每个 Item 都包含 Web 组件),这会导致内存暴涨和性能下降

安全考量

  1. JavaScript 控制:对于展示不可信内容的场景(如第三方网页),谨慎开启 javaScriptAccess。某些场景下禁用 JS 可以防止恶意脚本执行

  2. 混合内容MixedMode.All 允许 HTTP/HTTPS 混合加载,这在开发阶段方便,但在生产环境中应设置为 MixedMode.CompatibilityMixedMode.Security 以提高安全性

  3. URL 白名单:如果你的应用只加载特定的几个网站,建议进行 URL 白名单校验,阻止用户导航到未知网站

  4. 文件访问:仅在必要时开启 fileAccess。如果开启,确保不会加载用户输入路径的本地文件,防止路径遍历漏洞

总结

Web 组件是 HarmonyOS NEXT 中功能最为丰富的组件之一。本文通过构建一个完整的"轻量浏览器"应用,展示了 Web 组件的核心用法:

  • import webview from '@ohos.web.webview':正确的模块导入方式
  • Web({ src, controller }):组件的声明与初始化
  • WebviewController:通过 loadUrlbackwardforwardrefresh 控制页面导航
  • 配置选项javaScriptAccessdomStorageAccessoverviewModeAccessfileAccessonlineImageAccessmixedMode
  • 事件回调onProgressChange(加载进度)、onPageBegin/onPageEnd(生命周期)、onTitleReceive(标题获取)
  • URL 处理:自动补全协议、空值校验、去重检查
  • 书签系统:添加/删除/查看/去重,使用不可变更新模式管理 @State 数组
  • 遮罩层设计:Stack + 半透明背景 + 白色卡片的弹窗模式
  • 导航按钮状态:根据历史记录状态动态控制按钮的启用/禁用和颜色

Web 组件将 Chromium 内核的强大能力封装在一个声明式 UI 组件中,让 HarmonyOS 开发者能够以熟悉的 ArkUI 开发模式来集成 Web 内容。无论是构建应用内浏览器、展示帮助文档,还是嵌入 H5 活动页面,Web 组件都能提供坚实的技术支撑。结合本文介绍的导航控制、进度指示、书签管理等交互模式,你可以构建出体验流畅、功能完整的 Web 浏览体验。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐