鸿蒙Next实现一个可以展示代码的组件 原创

auhgnixgnahz
发布于 2025-9-1 08:27
浏览
0收藏

最近想把日常开发练习总结的APP上架到应用市场,由于之前APP内容都是最终的效果演示,看着有些单调,于是打算把对应的源码也加入到里面,可以直接阅读,和文章里的代码展示是一样的。
最终效果:
鸿蒙Next实现一个可以展示代码的组件-鸿蒙开发者社区
实现过程:
1.不知道鸿蒙有没有支持的三方库可以直接引用实现,我没有去查,最近刚好写Web的使用,正好可以结合HTML展示
2.对于一个移动端的开发程序员,写一个类似于Markdown的展示效果,也无从下手,于是找了AI帮忙,让他帮我写这个HTML,然后简单调试,直到效果满意
3.HTML中引用了Prism JS库,做过前端的同学可能了解,由于我想上架单机APP,所以就把这个js文件下载到了本地引用
4.Web与原生交互到这里肯定已经很熟悉了,只要将想要展示的代码通过js方法传入html就可以了
需要注意的点
测试过程中,有个坑需要注意,代码复制出来有很多特殊符号和 \ ,导致传入html后不能显示,所以需要对字符串进行格式化的处理。
展示代码的HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ArkTS代码展示</title>
    <!-- 引入Prism样式(确保与HTML同目录) -->
    <link rel="stylesheet" href="prism.css">
    <!-- 引入Prism核心库和TypeScript语法支持(确保与HTML同目录) -->
    <script src="prism.js"></script>
    <style>
        /* 重置默认样式,避免额外边距 */
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        /* 页面背景:轻微灰色,与代码区区分 */
        body {
            background-color: #f5f5f5;
            padding: 10px; /* 可选:给页面加少量内边距,避免代码贴边 */
        }
        /* 代码容器:仅保留代码区域,去掉顶部黑边(删除原头部相关样式) */
        pre {
            /* 代码区深色背景(Prism主题默认深色,如需浅色可改#fff) */
            background-color: #1d1f21;
            /* 代码内边距,确保文字不贴边 */
            padding: 16px;
            /* 移动端长代码横向滚动(核心适配) */
            overflow-x: auto;
            /* 代码字体大小:适配手机阅读 */
            font-size: 14px;
            /* 行高:提升可读性 */
            line-height: 1.6;
            /* 可选:轻微圆角,避免生硬(不需要可删除) */
            border-radius: 6px;
            /* 可选:轻微阴影,突出代码区(不需要可删除) */
            box-shadow: 0 1px 3px rgba(0,0,0,0.1);
        }
        /* 代码字体:等宽字体,确保代码格式对齐 */
        code {
            font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
            color: #ccc; /* 代码默认文字色,与深色背景适配 */
        }
    </style>
</head>
<body>
<!-- 仅保留代码展示核心区域:pre + code -->
<pre><code class="language-typescript" id="codeDisplay"></code></pre>
<script>
    /**
     * 接收并展示ArkTS代码的方法
     * @param {string} code - 传入的ArkTS源代码
     */
    function displayCode(code) {
        const codeElement = document.getElementById('codeDisplay');
        // 设置代码内容(空值时显示提示)
        codeElement.textContent = code || '未传入代码,请调用 displayCode(代码字符串)';
        // 触发Prism语法高亮
        Prism.highlightElement(codeElement);
    }
</script>
</body>
</html>

展示代码的组件

import { webview } from '@kit.ArkWeb'
import { util } from '@kit.ArkTS'
import { CaseRouterList } from '../model/CaseRouterList'

@Builder
export function CodeDisplayPage_Builder() {
  CodeDisplayPage()
}
@Entry
@ComponentV2
struct CodeDisplayPage{
  pageInfos: NavPathStack = new NavPathStack()
  private webviewController: WebviewController = new webview.WebviewController()
  @Local arkTSCode:string=''
  @Local title:string=''
  build() {
    NavDestination(){
      Scroll(){
        Column(){
          Web({
            src: $rawfile('blank-arkts-display.html'),
            controller: this.webviewController,
            renderMode: RenderMode.SYNC_RENDER
          })
            .layoutMode(WebLayoutMode.FIT_CONTENT) // 设置为Web组件大小自适应页面内容
            .overScrollMode(OverScrollMode.NEVER) // 设置过滚动模式为关闭状态
            .onPageEnd((event) => {
              let js = "displayCode('" + this.arkTSCode
                // .replace(/'/g, '\\\'')
                // .replace(/\n/g, '\\n')
                // .replace(/\r/g, '\\r')
                .replaceAll('\'', '\\\'')
                .replaceAll('\n', '\\n')
                .replaceAll('\r', '\\r')
                + "')";
              this.webviewController.runJavaScript(js)
            })
        }
      }
    }
    .onReady(async (context: NavDestinationContext) => {
      this.pageInfos = context.pathStack
      let parms:Array<string> = this.pageInfos.getParamByName("CodeDisplayPage") as Array<string>
      let codePath:string=''
      if (parms.length>0) {
        let codeRouter : CaseRouterList= JSON.parse(parms[0])
        this.title=codeRouter.pageName
        codePath=codeRouter.pageRouter
      }
      let getJson = await getContext(this).resourceManager.getRawFileContent('code/'+codePath+'.ets');
      let textDecoderOptions: util.TextDecoderOptions = { ignoreBOM : true };
      let textDecoder = util.TextDecoder.create('utf-8',textDecoderOptions);
      this.arkTSCode = textDecoder.decodeToString(getJson);
    })
    .title(this.title)
  }
}

注意:
1.我这里是将要展示的代码放到了rawfile资源下,通过传入的文件名,直接读取文件里的全部代码,然后调用js展示出来。
2.读取的代码需要处理一下 ’ \n \r ,要全部替换,具体看代码

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
标签
1
收藏
回复
举报
回复
    相关推荐