Bootstrap

鸿蒙网络编程系列46-仓颉版Web组件加载网页的三种方式

1. Web组件简介

本系列的第18篇文章《鸿蒙网络编程系列18-Web组件加载网页的四种方式示例》中,使用ArkTS语言基于API 9环境演示了Web组件四种加载网页内容的方式,其中就包括使用WebviewController的loadData方法直接加载HTML脚本的方式。不过,目前的仓颉版本还不支持loadData方法,因此,本文将基于API 12环境演示Web组件加载网页的其他三种方式。

2. Web组件加载网页演示

本示例运行后的页面如图所示:

在这种默认的情况下,使用的是加载资源文件的方式,也就是预先把html文件作为资源文件嵌入到应用中,然后在初始化web组件时作为src属性传入:

Web(src: @rawfile("index.html"), controller: controller)

第二种方式是直接加载网址,输入网址后,单击网址后面的“加载”按钮即可进行网页加载,如图所示:

第三种方式是加载本地html文件,单击“选择”按钮,选择本地html文件,如图所示:

选择文件后,单击“完成”按钮回到主界面,再单击“加载按钮”即可加载本地html文件,如图所示:

3. HWeb组件加载网页示例编写

下面详细介绍创建该示例的步骤(确保DevEco Studio已安装仓颉插件)。

步骤1:创建[Cangjie]Empty Ability项目。

步骤2:在module.json5配置文件加上对权限的声明:

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

这里添加了访问互联网的权限。

步骤3:在build-profile.json5配置文件加上仓颉编译架构:

"cangjieOptions": {
      "path": "./src/main/cangjie/cjpm.toml",
      "abiFilters": ["arm64-v8a", "x86_64"]
    }

步骤4:在main_ability.cj文件里添加如下的引用:

import ohos.ability.*

然后定义变量globalContext:

var globalContext: Option<AbilityContext> = Option<AbilityContext>.None

在onCreate函数里添加如下的代码:

globalContext = this.context

步骤5:创建index.html文件,并添加如下的代码:

<!-- index.html -->
<!DOCTYPE html>
<html>

<body style="font-size: large;text-align: center;">
<div style="color:blue">Hello HarmonyOS Next</div>
<div>Load with resource file</div>
</body>

</html>

把index.html文件作为资源文件嵌入到应用中:

步骤6:在index.cj文件里添加如下的代码:

package ohos_app_cangjie_entry

import ohos.base.*
import ohos.component.*
import ohos.state_manage.*
import ohos.state_macro_manage.*
import std.collection.HashMap
import ohos.net.http.*
import ohos.file_picker.*
import ohos.ability.getStageContext
import ohos.ability.*
import ohos.file_fs.*
import ohos.webview.*

@Entry
@Component
class EntryView {
    @State
    var title: String = '仓颉版Web加载示例';

    //要加载的网址
    @State
    var webUrl: String = "https://******"
    //要加载的文件
    @State
    var loadFileUri: String = ""

    let scroller: Scroller = Scroller()
    let controller: WebviewController = WebviewController()
    func build() {
        Row {
            Column {
                Text(title).fontSize(14).fontWeight(FontWeight.Bold).width(100.percent).textAlign(TextAlign.Center).
                    padding(10)

                Flex(FlexParams(justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center)) {
                    Text("网址:").fontSize(14)

                    TextInput(text: webUrl).onChange({
                        value => webUrl = value
                    }).width(100).fontSize(11).flexGrow(1)

                    Button("加载").onClick {
                        evt => this.controller.loadUrl(this.webUrl);
                    }.width(70).fontSize(14)
                }.width(100.percent).padding(10)

                Flex(FlexParams(justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center)) {
                    Text("文件:").fontSize(14)

                    TextInput(text: loadFileUri).onChange({
                        value => loadFileUri = value
                    }).width(100).fontSize(11).flexGrow(1)

                    Button("选择").onClick {
                        evt => selectLoadFile();
                    }.width(70).fontSize(14)

                    Button("加载").onClick {
                        evt => loadLocalFile()
                    }.width(70).fontSize(14)
                }.width(100.percent).padding(10)

                Scroll(scroller) {
                    Web(src: @rawfile("index.html"), controller: controller).domStorageAccess(true).fileAccess(true).
                        padding(10).width(100.percent).backgroundColor(0xeeeeee)
                }.align(Alignment.Top).backgroundColor(0xeeeeee).height(300).flexGrow(1).scrollable(
                    ScrollDirection.Vertical).scrollBar(BarState.On).scrollBarWidth(20)
            }.width(100.percent).height(100.percent)
        }.height(100.percent)
    }

    //选择需要加载的文件
    func selectLoadFile() {
        let option = DocumentSelectOptions(maxSelectNumber: 1, selectMode: DocumentSelectMode.MIXED)
        let documentPicker = DocumentViewPicker(globalContext.getOrThrow())

        let documentSelectCallback = {
            errorCode: Option<AsyncError>, data: Option<Array<String>> => match (errorCode) {
                case Some(e) => ()
                case _ => match (data) {
                    case Some(value) => loadFileUri = value[0]
                    case _ => ()
                }
            }
        }
        documentPicker.select(documentSelectCallback, option: option)
    }

    //加载本地文件
    func loadLocalFile() {
        let segments = this.loadFileUri.split('/')
        //文件名称
        let fileName = segments[segments.size - 1] + ".html"

        //计划复制到的目标路径
        let realUri = globalContext.getOrThrow().filesDir + "/" + fileName

        //复制选择的文件到沙箱cache文件夹
        let file = FileFs.open(this.loadFileUri);
        FileFs.copyFile(file.fd, realUri)
        FileFs.close(file);
        this.controller.loadUrl("file://${realUri}");
    }
}

步骤7:编译运行,可以使用模拟器或者真机,在当前版本下,最好使用真机。

步骤8:按照本节第2部分“Web组件加载网页演示”操作即可。

4. 代码分析

在加载本地文件时,需要复制本地文件到沙箱目录,再进行加载,加载时需要注意文件的路径格式,这里使用的是file前缀,对应代码如下所示:

func loadLocalFile() {
        let segments = this.loadFileUri.split('/')
        //文件名称
        let fileName = segments[segments.size - 1] + ".html"

        //计划复制到的目标路径
        let realUri = globalContext.getOrThrow().filesDir + "/" + fileName

        //复制选择的文件到沙箱cache文件夹
        let file = FileFs.open(this.loadFileUri);
        FileFs.copyFile(file.fd, realUri)
        FileFs.close(file);
        this.controller.loadUrl("file://${realUri}");
    }

(本文作者原创,除非明确授权禁止转载)

本文源码地址:
https://gitee.com/zl3624/harmonyos_network_samples/tree/master/code/web/WebDemo4Cj

本系列源码地址:
https://gitee.com/zl3624/harmonyos_network_samples

;