Sử dụng Thành Phần Web trong HarmonyOS: Tải Nội Dung và Cấu Hình Tương Tác

Để tích hợp thành phần Web vào ứng dụng HarmonyOS, cần khai báo quyền truy cập mạng và thiết lập bộ điều khiển trình duyệt phù hợp. Dưới đây là hướng dẫn triển khai các trường hợp phổ biến: tải trang từ URL, nội dung cục bộ, dữ liệu HTML động, cũng như cấu hình chế độ tối, chọn tệp và mở cửa sổ mới.

1. Khai báo quyền bắt buộc

Trước khi sử dụng chức năng mạng, ứng dụng phải yêu cầu quyền ohos.permission.INTERNET trong tệp module.json5:

"requestPermissions": [
  {
    "name": "ohos.permission.INTERNET"
  }
]

2. Tải nội dung web

2.1 Tải từ URL trực tuyến

Sử dụng WebviewController để điều khiển luồng điều hướng:

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

@Entry
@Component
struct BrowserView {
  private browserCtrl: webView.WebviewController = new webView.WebviewController();

  build() {
    Column({ space: 12 }) {
      Button('Truy cập trang chủ')
        .onClick(() => {
          try {
            this.browserCtrl.loadUrl('https://blog.csdn.net/aa2528877987');
          } catch (err) {
            console.error(`Lỗi: ${err.code} – ${err.message}`);
          }
        })
      
      Web({ src: 'https://www.baidu.com', controller: this.browserCtrl })
        .width('100%')
        .height(600)
    }
  }
}

2.2 Tải tài nguyên cục bộ

Tệp HTML được lưu trong thư mục resources/base/rawfile/. Gọi bằng toán tử $rawfile():

@Entry
@Component
struct LocalWebView {
  private ctrl: webView.WebviewController = new webView.WebviewController();

  build() {
    Column({ space: 10 }) {
      Button('Tải local1.html')
        .onClick(() => {
          try {
            this.ctrl.loadUrl($rawfile('local1.html'));
          } catch (e) {
            console.warn('Không thể tải tệp cục bộ:', e);
          }
        })

      Web({ src: $rawfile('local.html'), controller: this.ctrl })
        .width('100%')
        .height(500)
    }
  }
}

Ví dụ nội dung local.html:

<!DOCTYPE html>
<html>
  <body>
    <h2>Chào mừng đến với ứng dụng HarmonyOS</h2>
    <p>Nội dung được tải từ tài nguyên cục bộ.</p>
  </body>
</html>

2.3 Nhúng HTML dưới dạng chuỗi

Dùng phương thức loadData() để hiển thị nội dung HTML được tạo động:

@Entry
@Component
struct DynamicHtmlView {
  private ctrl: webView.WebviewController = new webView.WebviewController();

  build() {
    Column({ space: 8 }) {
      Button('Hiển thị HTML nội tuyến')
        .onClick(() => {
          const htmlContent = `
            <html>
              <head><meta charset="UTF-8"></head>
              <body style="background:#f0f8ff; padding:20px;">
                <h3>Dữ liệu HTML được tạo tại thời điểm chạy</h3>
                <p>Mã hóa: UTF-8 | Loại nội dung: text/html</p>
              </body>
            </html>
          `;
          this.ctrl.loadData(htmlContent, 'text/html', 'UTF-8');
        })

      Web({ src: 'https://example.com', controller: this.ctrl })
        .width('100%')
        .height(450)
    }
  }
}

3. Cấu hình hành vi nâng cao

3.1 Chế độ tối

Hỗ trợ ba chế độ ánh sáng/tối qua thuộc tính darkMode(), kết hợp với forceDarkAccess() để ép buộc giao diện tối độc lập:

@Entry
@Component
struct ThemedWebView {
  private ctrl: webView.WebviewController = new webView.WebviewController();
  @State darkPolicy: WebDarkMode = WebDarkMode.Auto;
  @State enforceDark: boolean = false;

  build() {
    Column() {
      Web({ src: 'https://example.com', controller: this.ctrl })
        .darkMode(this.darkPolicy)
        .forceDarkAccess(this.enforceDark)
    }
  }
}

3.2 Xử lý tải tệp lên

Sự kiện onShowFileSelector cho phép tùy chỉnh danh sách tệp người dùng có thể chọn:

@Entry
@Component
struct FileUploadView {
  private ctrl: webView.WebviewController = new webView.WebviewController();

  build() {
    Column() {
      Web({ src: $rawfile('upload-page.html'), controller: this.ctrl })
        .onShowFileSelector((event) => {
          // Trả về mảng đường dẫn tệp đã chọn
          const selectedPaths = [
            '/data/storage/el2/base/haps/entry/files/images/avatar.png',
            '/data/storage/el2/base/haps/entry/files/docs/report.pdf'
          ];
          event.result.handleFileList(selectedPaths);
          return true;
        })
    }
  }
}

Ví dụ tệp upload-page.html:

<html>
  <body>
    <h3>Chọn tệp để tải lên</h3>
    <input type="file" id="uploader" accept="image/*,.pdf">
    <button onclick="document.getElementById('uploader').click()">
      Mở trình chọn tệp
    </button>
  </body>
</html>

3.3 Mở liên kết trong cửa sổ mới

Kích hoạt hỗ trợ đa cửa sổ bằng multiWindowAccess(true) và xử lý sự kiện onWindowNew để khởi tạo Web mới trong dialog:

@CustomDialog
struct PopupWebView {
  controller?: CustomDialogController;
  private innerCtrl: webView.WebviewController = new webView.WebviewController();

  build() {
    Column() {
      Web({ src: '', controller: this.innerCtrl })
        .javaScriptAccess(true)
        .multiWindowAccess(false)
        .onWindowExit(() => {
          if (this.controller) this.controller.close();
        })
    }
  }
}

@Entry
@Component
struct MainWebView {
  private mainCtrl: webView.WebviewController = new webView.WebviewController();
  private popupDialog: CustomDialogController | null = null;

  build() {
    Column() {
      Web({ src: $rawfile('popup-trigger.html'), controller: this.mainCtrl })
        .javaScriptAccess(true)
        .multiWindowAccess(true)
        .allowWindowOpenMethod(true)
        .onWindowNew((event) => {
          if (this.popupDialog) this.popupDialog.close();
          
          const newCtrl = new webView.WebviewController();
          this.popupDialog = new CustomDialogController({
            builder: PopupWebView({ innerCtrl: newCtrl })
          });
          this.popupDialog.open();
          event.handler.setWebController(newCtrl);
        })
    }
  }
}

Ví dụ tệp popup-trigger.html:

<html>
  <body>
    <button onclick="window.open('https://harmonyos.com', '_blank', 'width=400,height=300')">
      Mở trang mới
    </button>
  </body>
</html>

Thẻ: HarmonyOS webview ohos.web.webview ets multiwindow

Đăng vào ngày 17 tháng 6 lúc 01:31