鸿蒙学习实战之路-Web 页面适配最佳实践

Web 页面适配是 HarmonyOS 应用开发中常见的需求,本文将介绍如何在鸿蒙应用中实现 Web 页面的最佳适配方案,包括基础使用、响应式布局、视频播放适配、深色模式适配等内容。

关于本文

自己学习并使用 HarmonyOS Web 组件的记录,旨在帮助小伙伴们少走弯路

华为开发者联盟-Web 组件文档永远是你的好伙伴,请收藏!

  • 本文并不能代替官方文档,所有的内容也都是基于官方文档+自己尝试的记录。
  • 基本所有章节基本都会附上对应的文档链接,强烈建议你点看看看
  • 所有结合代码操作的部分,建议自己动手尝试一下

代码测试环境

环境/工具 版本/说明
DevEco Studio 5.0.3.400
HarmonyOS SDK API Version 12
Node.js 18.19.0
测试设备 HarmonyOS 4.0+ 模拟器

1. 概述

在 HarmonyOS 应用开发中,Web 组件是实现 Web 页面加载和交互的核心组件。通过 Web 组件,开发者可以在鸿蒙应用中无缝集成 Web 内容,实现丰富的跨平台体验。Web 页面适配是确保 Web 内容在不同设备、不同系统主题下都能良好展示的关键技术。

1.1 Web 组件基本概念

Web 组件(WebView)是 HarmonyOS 提供的用于加载和显示 Web 页面的组件,它基于开源的 Chromium 内核,支持现代 Web 标准。

1.2 Web 页面适配的应用场景

  • 内容展示类应用:需要展示大量 Web 内容的新闻、资讯类应用
  • 电商应用:商品详情页、活动页面等需要灵活定制的内容
  • 教育应用:在线课程、学习资料等需要丰富交互的内容
  • 企业应用:内部系统、OA 办公等需要快速迁移的 Web 应用

2. Web 组件基础使用

2.1 配置 Web 组件依赖

在项目的module.json5文件中添加网络访问权限:

{
  module: {
    // ...其他配置
    abilities: [
      {
        // ...其他配置
        skills: [
          {
            // ...其他配置
          },
        ],
      },
    ],
    requestPermissions: [
      {
        name: "ohos.permission.INTERNET",
      },
    ],
  },
}

2.2 基本的 Web 组件使用

import { webview } from '@kit.ArkWeb';
import { Column, Text, TitleBar, Web, Flex, Image } from '@kit.ArkUI';

@Component
export struct WebPage {
  // 创建Web控制器
  private webviewController: webview.WebviewController = new webview.WebviewController();
  // Web页面加载状态
  @State loadingProgress: number = 0;
  // 页面标题
  @State pageTitle: string = '加载中...';

  build() {
    Column() {
      // 标题栏
      TitleBar() {
        Text(this.pageTitle).fontSize(20).fontWeight(500);
      }
      .backgroundColor($r('app.color.primary'))
      .height(56)

      // 加载进度条
      if (this.loadingProgress < 100) {
        Flex() {
          Flex()
            .width(`${this.loadingProgress}%`)
            .height(3)
            .backgroundColor($r('app.color.primary'))
        }
        .width('100%')
        .height(3)
        .backgroundColor('#E0E0E0')
      }

      // Web组件
      Web({
        src: 'https://developer.huawei.com/consumer/cn/',
        controller: this.webviewController
      })
      .width('100%')
      .height('100%')
      // 加载进度变化回调
      .onProgressChange((event) => {
        this.loadingProgress = event.newProgress;
      })
      // 页面标题变化回调
      .onTitleReceive((event) => {
        this.pageTitle = event.title;
      })
      // 页面加载完成回调
      .onPageEnd(() => {
        console.info('Web页面加载完成');
      })
    }
    .width('100%')
    .height('100%')
  }
}

3. 页面资源管理

3.1 本地 Web 页面资源

将 Web 页面资源放置在项目的src/main/resources/rawfile目录下:

src/main/resources/
└── rawfile/
    └── my_web_page/
        ├── index.html
        ├── css/
        │   └── style.css
        ├── js/
        │   └── script.js
        └── images/
            └── logo.png

3.2 加载本地 Web 页面

Web({
  src: $rawfile("my_web_page/index.html"),
  controller: this.webviewController,
})
  .width("100%")
  .height("100%");

3.3 本地资源路径处理

在 HTML 文件中,使用相对路径引用本地资源:

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>本地Web页面</title>
    <link rel="stylesheet" href="css/style.css" />
  </head>
  <body>
    <div class="container">
      <img src="images/logo.png" alt="Logo" />
      <h1>欢迎使用本地Web页面</h1>
      <p>这是一个在HarmonyOS应用中加载的本地Web页面示例。</p>
    </div>
    <script src="js/script.js"></script>
  </body>
</html>

4. 响应式布局适配

4.1 视口设置

在 HTML 文件的 head 标签中设置正确的 viewport:

<meta
  name="viewport"
  content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>

4.2 使用 CSS 媒体查询

/* 基础样式 */
.container {
  width: 100%;
  padding: 16px;
}

/* 平板设备适配 */
@media (min-width: 768px) {
  .container {
    max-width: 720px;
    margin: 0 auto;
    padding: 24px;
  }
}

/* 桌面设备适配 */
@media (min-width: 1024px) {
  .container {
    max-width: 960px;
    padding: 32px;
  }
}

以下是不同断点下的 Web 页面适配效果:

断点 效果图
sm sm断点效果
md md断点效果
lg lg断点效果

4.3 HarmonyOS 中的 Web 组件适配

在 ArkTS 中,根据不同设备类型调整 Web 组件的大小:

import { device } from '@kit.ArkUI';

@Component
export struct AdaptiveWebPage {
  private webviewController: webview.WebviewController = new webview.WebviewController();

  build() {
    Column() {
      Web({
        src: 'https://developer.huawei.com/consumer/cn/',
        controller: this.webviewController
      })
      // 根据设备类型调整宽度
      .width(device.isTablet ? '80%' : '100%')
      .height('100%')
    }
    .width('100%')
    .height('100%')
    .alignItems(HorizontalAlign.Center)
  }
}

4.4 常用响应式布局模式

在 Web 开发中,常用的响应式布局模式有:

  1. 流式布局:使用百分比宽度,让元素随容器大小变化

  2. 弹性布局:使用 Flexbox 实现灵活的一维布局

  3. 栅格布局:使用 CSS Grid 实现二维网格布局

    栅格布局(宫格布局)是一种强大的二维布局系统,可以将页面划分为多个行和列,实现复杂的布局效果。

    宫格布局示意图

    以下是宫格布局的示例代码:

    <!DOCTYPE html>
    <html lang="zh-CN">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>宫格布局示例</title>
        <style>
          /* 宫格容器 */
          .grid-container {
            display: grid;
            grid-template-columns: repeat(3, 1fr); /* 3列布局 */
            grid-template-rows: repeat(2, 100px); /* 2行布局,每行高度100px */
            gap: 10px; /* 网格间距 */
            padding: 10px;
          }
    
          /* 宫格项 */
          .grid-item {
            background-color: #4caf50;
            color: white;
            text-align: center;
            padding: 20px;
            font-size: 18px;
          }
        </style>
      </head>
      <body>
        <div class="grid-container">
          <div class="grid-item">1</div>
          <div class="grid-item">2</div>
          <div class="grid-item">3</div>
          <div class="grid-item">4</div>
          <div class="grid-item">5</div>
          <div class="grid-item">6</div>
        </div>
      </body>
    </html>
    

    上述示例代码的运行效果如下:

    宫格布局示例代码效果图

  4. 自适应布局:为不同设备尺寸创建不同的布局方案

4.5 案例:轮播布局的响应式适配

轮播布局(轮播图)是 Web 开发中常用的组件之一,需要特别注意其响应式适配。轮播布局的适配关键点包括:

  • 控制轮播元素的尺寸:使用媒体查询和断点设置不同设备下的轮播图尺寸
  • 控制轮播元素的间距:根据布局方式选择合适的间距控制方法
  • 控制每次轮播的位移距离:根据实现方案控制位移步长

以下是轮播布局在不同断点下的适配效果:

断点 效果图
sm sm断点轮播效果
md md断点轮播效果
lg lg断点轮播效果

4.6 案例:自定义弹窗的响应式适配

在多设备适配中,弹窗组件需要根据设备尺寸调整大小和布局。在小屏幕设备上使用紧凑布局,在大屏幕设备上使用更大的弹窗展示,以避免内容过小不易看清。

以下是自定义弹窗在不同断点下的适配效果:

断点 效果图
sm sm断点弹窗效果
md md断点弹窗效果
lg lg断点弹窗效果

5. 视频播放适配

5.1 视频播放基础配置

在 HTML 文件中使用 video 标签:

<video id="myVideo" controls autoplay muted>
  <source src="videos/sample.mp4" type="video/mp4" />
  您的浏览器不支持HTML5视频。
</video>

5.2 视频全屏适配

Web({
  src: $rawfile("my_web_page/index.html"),
  controller: this.webviewController,
})
  .width("100%")
  .height("100%")
  // 视频全屏变化回调
  .onFullScreenChange((event) => {
    console.info(`视频全屏状态变化: ${event.fullScreen}`);
  });

5.3 视频播放优化

// 启用硬件加速
Web({
  src: "https://example.com/video.html",
  controller: this.webviewController,
})
  .width("100%")
  .height("100%")
  // 设置Web组件配置
  .webConfig({
    // 启用硬件加速
    hardwareAcceleration: true,
    // 启用媒体自动播放
    mediaPlaybackRequiresUserGesture: false,
  });

6. 深色模式适配

6.1 监听系统深色模式变化

import { AppStorage } from '@kit.ArkUI';

@Component
export struct DarkModeWebPage {
  private webviewController: webview.WebviewController = new webview.WebviewController();
  // 系统深色模式状态
  @StorageProp('darkMode') darkMode: boolean = false;

  build() {
    Column() {
      Web({
        src: 'https://developer.huawei.com/consumer/cn/',
        controller: this.webviewController
      })
      .width('100%')
      .height('100%')
      // 监听深色模式变化
      .onWindowFocus(() => {
        this.updateWebTheme();
      })
    }
    .width('100%')
    .height('100%')
    // 监听系统主题变化
    .onThemeChange((darkMode) => {
      this.darkMode = darkMode;
      this.updateWebTheme();
    })
  }

  // 更新Web页面主题
  private updateWebTheme() {
    if (this.darkMode) {
      // 注入JavaScript代码,切换到深色模式
      this.webviewController.runJavaScript("document.documentElement.setAttribute('data-theme', 'dark');");
    } else {
      // 切换到浅色模式
      this.webviewController.runJavaScript("document.documentElement.setAttribute('data-theme', 'light');");
    }
  }
}

6.2 Web 页面的深色模式 CSS

/* 浅色模式 */
:root {
  --background-color: #ffffff;
  --text-color: #333333;
  --border-color: #e0e0e0;
}

/* 深色模式 */
[data-theme="dark"] {
  --background-color: #1a1a1a;
  --text-color: #ffffff;
  --border-color: #404040;
}

/* 使用CSS变量 */
body {
  background-color: var(--background-color);
  color: var(--text-color);
  border-color: var(--border-color);
}

7. 性能优化

7.1 页面加载优化

Web({
  src: "https://developer.huawei.com/consumer/cn/",
  controller: this.webviewController,
})
  .width("100%")
  .height("100%")
  // 预加载DNS
  .dnsPrefetch("https://developer.huawei.com")
  // 启用缓存
  .webConfig({
    // 启用页面缓存
    cacheMode: webview.CacheMode.LOAD_DEFAULT,
    // 启用DOM存储
    domStorageAccess: true,
  });

7.2 资源加载控制

// 拦截并控制资源加载
Web({
  src: "https://developer.huawei.com/consumer/cn/",
  controller: this.webviewController,
})
  .width("100%")
  .height("100%")
  // 资源请求拦截
  .onResourceLoadIntercept((event) => {
    const resourceUrl = event.request.getRequestUrl();
    // 过滤广告资源
    if (resourceUrl.includes("ad.")) {
      return false;
    }
    return true;
  });

7.3 页面渲染优化

// 启用平滑滚动
Web({
  src: "https://developer.huawei.com/consumer/cn/",
  controller: this.webviewController,
})
  .width("100%")
  .height("100%")
  .webConfig({
    // 启用平滑滚动
    smoothScrollEnabled: true,
    // 减少动画帧延迟
    animationFrameRate: webview.AnimationFrameRate.HIGH,
  });

8. 安全考虑

8.1 安全的资源加载

// 只允许加载HTTPS资源
Web({
  src: "https://developer.huawei.com/consumer/cn/",
  controller: this.webviewController,
})
  .width("100%")
  .height("100%")
  .webConfig({
    // 启用安全浏览
    safeBrowsingEnabled: true,
    // 禁用混合内容
    mixedContentMode: webview.MixedContentMode.BLOCK_ALL,
  });

8.2 JavaScript 注入安全

// 安全地注入JavaScript代码
private injectSafeScript() {
  // 只注入经过验证的代码
  const safeScript = "console.log('安全的JavaScript注入');";
  this.webviewController.runJavaScript(safeScript);
}

8.3 敏感信息保护

// 清除WebView缓存和Cookie
private clearWebData() {
  // 清除缓存
  this.webviewController.clearCache(true);
  // 清除Cookie
  this.webviewController.clearCookies();
  // 清除表单数据
  this.webviewController.clearFormData();
}

9. Web 组件与 Native 通信

9.1 Native 调用 Web 页面方法

// 调用Web页面中的JavaScript方法
private callWebMethod() {
  const message = 'Hello from HarmonyOS';
  this.webviewController.runJavaScript(`showMessage("${message}")`);
}

9.2 Web 页面调用 Native 方法

Web({
  src: $rawfile("my_web_page/index.html"),
  controller: this.webviewController,
})
  .width("100%")
  .height("100%")
  // 注册JavaScript接口
  .javaScriptProxy({
    object: {
      // 定义Native方法
      showToast: (message: string) => {
        // 显示Toast
        prompt.showToast({
          message: message,
          duration: prompt.Duration.SHORT,
        });
      },
      // 获取设备信息
      getDeviceInfo: () => {
        return {
          model: device.deviceModel,
          osVersion: device.osVersion,
        };
      },
    },
    name: "harmonyOS",
    methodList: ["showToast", "getDeviceInfo"],
    controller: this.webviewController,
  });

在 Web 页面中调用 Native 方法:

// 调用Native的showToast方法
harmonyOS.showToast("Hello from Web Page");

// 调用Native的getDeviceInfo方法
const deviceInfo = harmonyOS.getDeviceInfo();
console.log("设备信息:", deviceInfo);

10. 最佳实践总结

10.1 开发建议

  1. 合理规划 Web 资源:根据应用需求选择本地资源或远程资源,本地资源加载更快,远程资源便于更新
  2. 优化页面加载速度:使用缓存、预加载、资源压缩等技术提升页面加载速度
  3. 确保响应式设计:使用 CSS 媒体查询和弹性布局,确保在不同设备上都有良好的显示效果
  4. 适配深色模式:支持系统深色模式,提升用户体验
  5. 优化视频播放:启用硬件加速,支持全屏播放,确保视频流畅播放

10.2 性能优化

  1. 减少重绘和回流:优化 CSS 和 JavaScript,减少 DOM 操作
  2. 启用硬件加速:对视频、动画等资源启用硬件加速
  3. 控制资源加载:拦截不必要的资源请求,减少网络流量
  4. 合理使用缓存:根据资源类型设置合适的缓存策略

10.3 安全防护

  1. 使用 HTTPS 协议:确保所有网络请求都使用 HTTPS 协议
  2. 限制 JavaScript 权限:只授予必要的 JavaScript 接口权限
  3. 保护用户隐私:定期清理缓存和 Cookie,保护用户敏感信息
  4. 验证输入内容:对用户输入和 Web 页面返回的内容进行验证

11. 常见问题与解决方案

11.1 Web 页面加载缓慢

问题:Web 页面加载时间过长,影响用户体验

解决方案

  • 启用页面缓存
  • 预加载常用资源
  • 压缩 HTML、CSS 和 JavaScript 文件
  • 减少 HTTP 请求数量

11.2 视频播放卡顿

问题:Web 页面中的视频播放不流畅,出现卡顿

解决方案

  • 启用硬件加速
  • 优化视频格式和编码
  • 使用适当的视频分辨率
  • 确保网络连接稳定

11.3 深色模式适配问题

问题:Web 页面在深色模式下显示异常

解决方案

  • 使用 CSS 变量定义主题颜色
  • 监听系统深色模式变化
  • 确保所有 UI 元素都支持深色模式

12. 总结

Web 页面适配是 HarmonyOS 应用开发中的重要内容,通过本文的介绍,您应该已经掌握了 Web 组件的基本使用、响应式布局适配、视频播放适配、深色模式适配、性能优化和安全防护等方面的知识。

在实际应用开发中,应根据具体业务需求和场景选择合适的适配策略,并注意性能优化和安全考虑。希望本文的内容能够对您有所帮助,祝您在鸿蒙开发之路上越走越远!

参考文档

  1. 华为开发者联盟-ArkWeb
  2. 华为开发者联盟-Web 与 Native 通信
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐