HarmonyOS 使用富文本组件和web组件加载html页面

986 阅读3分钟

HarmonyOS 使用富文本组件和web组件加载html页面

引言

在鸿蒙开发中有些场景需要使用html的功能才能完成,比如关键字高亮,特殊格式的文本等,因此RichText组件和web组件的作用就显的格外重要。

RichText富文本

带有html标签包裹住的文本叫做富文本例如:<h1>hello</h1><p>hello</p>

直接写会出现文字显示非常小,看不清楚的问题列如:RichText(<h1>这是一个富文本<h1>)

可以使用一段html结构+div 设置字体大小来解决

RichText(`
            <html>
            <body>
              <div style="font-size:45px"><h1>这是一个富文本</h1></div>
            <body>
            </html>
            `)

使用富文本来显示html格式的内容会很方便但是也存在着性能方面的问题。如RichText组件比较消耗内存资源,在List组件中循环重复使用RichText时,会出现卡顿、滑动响应慢等现象,这时建议使用RichEditor组件

web组件

web组件可以加载在线网页,沙箱中的页面,项目中entry/src/main/resources/rawfile下的静态html网页,可以说是功能相当强大。

但是需要注意,访问在线网页时需添加网络权限:ohos.permission.INTERNET,web组件不跟随转场动画。在ArkTS中web组件不再限于一个页面仅支持一个web组件,可以在同一个页面中使用多个web组件但是需要注意,同一页面的多个Web组件,必须绑定不同的WebviewController。

加载在线网页

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

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

  build() {
    Column() {
      Web({ src: 'www.baidu.com', controller: this.controller })
        .width('100%')
    }
    .width('100%')
  }
}

请求来的在线网页是这个样子的

image.png

加载在线网页时需要开启模拟器的网络权限

image.png

加载本地网页

首选要在本地的目录下有html页面,html页面内容如下

<!doctype html>
<html>
<html>
<body>
<div style="font-size: 45px;">
   我是web组件加载的本地网页
</div>
</body>
</html>

image.png

ArkTS代码如下

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

@Entry
@Component
struct WebComponent {
  controller: webview.WebviewController = new webview.WebviewController();
  build() {
    Column() {
      // 通过$rawfile加载本地资源文件。
      Web({ src: $rawfile("My.html"), controller: this.controller })
    }
  }
}

如果成功加载就可以在模拟器上看到如下结果

image.png

加载沙箱路径下的本地资源文件

import fs from '@ohos.file.fs';
  @State url:string = ''
  str = `<!DOCTYPE html>
<html>
    <body>
    <div style="font-size: 45px;">
    <p>Hello World</p>
    </div>
    </body>
</html>`
  writehtml() {
    //往沙箱中写入
    try {
      const file = fs.openSync(getContext().cacheDir + '/My2.html', fs.OpenMode.WRITE_ONLY | fs.OpenMode.CREATE)//有了就只写入,如果原本有内容会被清空,没有就新建文件再写入
      fs.writeSync(file.fd,this.str)
      AlertDialog.show({
        message: '写入成功',
      })
      this.url = getContext().cacheDir + '/' + 'My2.html'  //获取写入沙箱中文件的地址
      AlertDialog.show({
      //看一下写入的地址是否正确
        message:this.url,
      })
//删除
//       fs.unlinkSync(getContext().cacheDir+ '/'+'My2.html')//fs删除指定目录下文件的同步方法
    } catch (err) {
      AlertDialog.show({
        message: JSON.stringify(err, null, 2),
      })
    }
  }

使用fs包中的writeSync同步方法,把str中的内容写入到沙箱中,写入成功的话可以在下图位置找到写入的文件

image.png base下面的路径一定要根据项目中的bundleName来确定,否则找不到写在沙箱中的文件。 如果需要删除可以单独运行fs.unlinkSync(getContext().cacheDir+ '/'+'My2.html')来删除,因为沙箱中的文件更改后没有权限保存,所以需要通过代码删除,也可以直接在模拟器中把应用卸载,清空沙箱中的缓存就会全部被清空。

通过如下代码来加载沙箱中的html文件

webviewController = new webview.WebviewController()
  aboutToAppear(): void {
    this.writehtml()
  }
  build() {
    Column() {
      if(this.url){
      Web({
        src: this.url,
        controller: this.webviewController
      })
        .height(300)
        .width('100%')
        .domStorageAccess(true)
        .fileAccess(true)
      }else{
        Text(`url为空`)
      }
    }
    .width('100%')
    .height('100%')
  }
}

如果成功可以在模拟器中看到加载的html页面

image.png

注: web组件的这两个属性必须开启才可以从缓存读取到内容,否则可能出现光占了位置却没有内容的情况。 .domStorageAccess(true).fileAccess(true)

总代码:

import fs from '@ohos.file.fs';
import { webview } from '@kit.ArkWeb';

export class GlobalContext {
  private constructor() {
  }

  private static instance: GlobalContext;
  private _objects = new Map<string, Object>();

  public static getContext(): GlobalContext {
    if (!GlobalContext.instance) {
      GlobalContext.instance = new GlobalContext();
    }
    return GlobalContext.instance;
  }

  getObject(value: string): Object | undefined {
    return this._objects.get(value);
  }

  setObject(key: string, objectClass: Object): void {
    this._objects.set(key, objectClass);
  }
}
@Entry
@Component
struct Index {
  @State url:string = ''
  str = `<!DOCTYPE html>
<html>
    <body>
    <div style="font-size: 45px;">
    <p>Hello World</p>
    </div>
    </body>
</html>`
  writehtml() {
    //往沙箱中写入
    try {
      const file = fs.openSync(getContext().cacheDir + '/My2.html', fs.OpenMode.WRITE_ONLY | fs.OpenMode.CREATE)
      fs.writeSync(file.fd,this.str)
      AlertDialog.show({
        message: '写入成功',
      })
      // 'file://' + file.path
      this.url = getContext().cacheDir + '/' + 'My2.html'
      AlertDialog.show({
        message:this.url,
      })
//删除
//       fs.unlinkSync(getContext().cacheDir+ '/'+'My2.html')
    } catch (err) {
      AlertDialog.show({
        message: JSON.stringify(err, null, 2),
      })
    }
  }
  webviewController = new webview.WebviewController()
  aboutToAppear(): void {
    this.writehtml()
  }
  build() {
    Column() {
      if(this.url){
      Web({
        src: this.url,
        controller: this.webviewController
      })
        .height(300)
        .width('100%')
        .domStorageAccess(true)
        .fileAccess(true)
      }else{
        Text(`url为空`)
      }
    }
    .width('100%')
    .height('100%')
  }
}