鸿蒙开发文档中有一节 加载本地页面 提到了可以通过 $rawfile
方法加载本地 HTML 网页:
Index.ets
1 | Web({ src: $rawfile("local.html"), controller: this.webviewController }) |
但是如果在 local.html 中需要引用一些静态资源,例如图片、JS、CSS 等,静态资源放在 local.html 同级目录下,会出现跨域的错误:
Console
1 | Access to ... at 'resource://...' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, arkweb, data, chrome-extension, chrome, https, chrome-untrusted. |
这是因为本地资源的 URL 是以 resource://
开头的,Web 组件没有这种类型 URL 的跨域处理策略。
怎样解决跨域问题?我想到了一种通过 onInterceptRequest
拦截请求解决跨域的方法,在此分享,该方法 不一定是最佳实践,但确实能够解决跨域。
解决加载本地资源的跨域问题
Index.ets
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | import url from '@ohos.url'; import web_webview from '@ohos.web.webview'; @Entry @Component struct Index { webviewController: web_webview.WebviewController = new web_webview.WebviewController(); responseResource: WebResourceResponse = new WebResourceResponse(); localMockUrl: string = 'http://myapp.local'; aboutToAppear() { // 配置Web开启调试模式 web_webview.WebviewController.setWebDebuggingAccess(true); } build() { Column() { Web({ // TODO: 把 local.html 修改为你自己的 html 文件路径 src: `${this.localMockUrl}/local.html`, controller: this.webviewController }) .onInterceptRequest((event) => { if (event) { // 拦截页面请求 const requestUrl = event.request.getRequestUrl() if (requestUrl.startsWith(this.localMockUrl)) { // 获取相对路径 const relativePath = url.URL.parseURL(requestUrl).pathname.replace(/^\//, ''); const resource = $rawfile(relativePath); this.responseResource.setResponseData(resource); this.responseResource.setResponseEncoding('utf-8'); let mimeType = "text/plain"; if (relativePath.endsWith(".html")) { mimeType = "text/html"; } else if (relativePath.endsWith(".css")) { mimeType = "text/css"; } else if (relativePath.endsWith(".js")) { mimeType = "text/javascript"; } else if (relativePath.endsWith(".png")) { mimeType = "image/png"; } else if (relativePath.endsWith(".gif")) { mimeType = "image/gif"; } else if (relativePath.endsWith(".svg")) { mimeType = "image/svg+xml"; } else if (relativePath.endsWith(".pdf")) { mimeType = "application/pdf"; } else { // TODO: 把你网页用到的所有静态资源的 mimeType 补充到上面这段逻辑中 } this.responseResource.setResponseMimeType(mimeType); this.responseResource.setResponseCode(200); this.responseResource.setReasonMessage('OK'); return this.responseResource; } } return null; }) } } } |
解决加载网络资源的跨域问题
如果跨域是因为 H5 需要向服务器请求获取数据,不是加载本地资源文件导致的,可以把上面代码中的 localMockUrl
改成和服务器相同的 origin(例如 http://api.xxx.com
,结尾不要带 /
),实现本地资源和服务器资源同域,并在 onInterceptRequest
中补充下面的判断:
1 2 3 4 5 | // 把这个判断改成你实际判断服务端请求的方式 if (relativePath.startsWith("api/")) { // 如果路径以 api/ 开头,代表这是一个服务器请求,返回 null 代表不拦截 return null; } |
效果:
还不明白的可以拉这个仓库自己试验: hm-cors-demo: harmony cors demo
代码在 entry/src/main/ets/pages/Index.ets
和 entry/src/main/resources/rawfile/local.html
里
最后
小编在之前的鸿蒙系统扫盲中,有很多朋友给我留言,不同的角度的问了一些问题,我明显感觉到一点,那就是许多人参与鸿蒙开发,但是又不知道从哪里下手,因为资料太多,太杂,教授的人也多,无从选择。有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)文档用来跟着学习是非常有必要的。
为了确保高效学习,建议规划清晰的学习路线,涵盖以下关键阶段:
希望这一份鸿蒙学习文档能够给大家带来帮助~
鸿蒙(HarmonyOS NEXT)最新学习路线
该路线图包含基础技能、就业必备技能、多媒体技术、六大电商APP、进阶高级技能、实战就业级设备开发,不仅补充了华为官网未涉及的解决方案
路线图适合人群:
IT开发人员:想要拓展职业边界
零基础小白:鸿蒙爱好者,希望从0到1学习,增加一项技能。
技术提升/进阶跳槽:发展瓶颈期,提升职场竞争力,快速掌握鸿蒙技术
2.视频教程+学习PDF文档
(鸿蒙语法ArkTS、TypeScript、ArkUI教程……)
纯血版鸿蒙全套学习文档(面试、文档、全套视频等)
鸿蒙APP开发必备
总结
参与鸿蒙开发,你要先认清适合你的方向,如果是想从事鸿蒙应用开发方向的话,可以参考本文的学习路径,简单来说就是:为了确保高效学习,建议规划清晰的学习路线