当前位置: 首页 > article >正文

使用cursor ai 开发 UniApp JSON 工具开发文档

使用cursor ai 开发 UniApp JSON 工具开发文档

1. 需求背景

在开发过程中,我们经常需要处理 JSON 数据,包括格式化、压缩、转义、Unicode 转换等操作。为了提高开发效率,我们决定开发一个功能完善的 JSON 工具页面,集成多种常用功能,并提供友好的用户界面和错误提示。

主要功能需求包括:

  • JSON 格式化与压缩
  • JSON 转义与去转义
  • Unicode 与中文互转
  • 带行号的代码编辑器
  • 精确的错误提示
  • 复制与清空功能

在线演示

演示地址: http://demo.xiyueta.com/case/web20250222/#/pages/debug/json
测试账号: demo
测试密码: 123456

使用效果

json工具

json工具

2. 技术选型

  • 前端框架:UniApp + Vue 3 (Composition API)
  • JSON 解析:jsonlint-mod(第三方库,提供更详细的错误信息)
  • UI 组件:自定义组件,不依赖第三方 UI 库
  • 样式:SCSS 预处理器

3. 功能实现

3.1 带行号的代码编辑器

实现带行号的代码编辑器是本项目的核心挑战之一。我们尝试了多种方案,最终采用了一种简单而有效的实现方式。

初始尝试:绝对定位 + 滚动同步

最初,我们尝试将行号区域和编辑区域分开,通过监听编辑区域的滚动事件来同步行号区域的滚动位置:

<view class="editor-main">
  <view class="line-numbers">
    <view class="line-numbers-content" :style="{ transform: `translateY(-${scrollTop}px)` }">
      <view v-for="n in lineCount" :key="n" class="line-number">{{ n }}</view>
    </view>
  </view>
  <textarea
    v-model="inputText"
    class="json-editor"
    @scroll="onScroll"
    ref="editorRef"
  />
</view>

<script>
// 处理滚动同步
const onScroll = (e) => {
  scrollTop.value = e.detail.scrollTop
}
</script>

问题:这种方法在不同平台上表现不一致,特别是在小程序中,滚动事件的处理和 DOM 操作存在限制,导致滚动同步不准确。

最终解决方案:单一滚动容器

最终,我们采用了一个更简单、更可靠的方法:将行号和编辑区域放在同一个滚动容器内,利用 flex 布局实现并排显示:

<scroll-view class="editor-scroll" scroll-y>
  <view class="editor-content">
    <view class="line-numbers">
      <view v-for="n in lineCount" :key="n" class="line-number">{{ n }}</view>
    </view>
    <textarea
      v-model="inputText"
      class="json-editor"
      :maxlength="-1"
      ref="editorRef"
    />
  </view>
</scroll-view>
.editor-content {
  display: flex;
  min-height: 100%;
  
  .line-numbers {
    width: 80rpx;
    flex-shrink: 0;
    background: #fafafa;
    border-right: 1px solid #ebeef5;
    padding: 20rpx 0;
    
    .line-number {
      height: 42rpx;
      line-height: 42rpx;
      text-align: right;
      padding-right: 10rpx;
      color: #909399;
      font-size: 28rpx;
    }
  }
  
  .json-editor {
    flex: 1;
    min-height: 100%;
    height: auto;
    padding: 20rpx;
    font-size: 28rpx;
    line-height: 42rpx;
    font-family: Consolas, Monaco, monospace;
    white-space: pre;
    border: none;
    outline: none;
    resize: none;
  }
}

这种方法的优势在于:

  • 行号和内容在同一个滚动容器中,自然同步滚动
  • 不需要额外的 JavaScript 代码来处理滚动同步
  • 跨平台兼容性好
  • 实现简单,性能更好

3.2 JSON 解析与错误处理

最初,我们使用浏览器内置的 JSON.parse() 方法进行 JSON 解析,但发现它提供的错误信息有限,难以精确定位错误位置。

问题:错误定位不准确

使用 JSON.parse() 时,错误信息通常只包含字符位置,没有行号和列号信息:

try {
  const obj = JSON.parse(inputText.value)
  // 处理成功情况
} catch (e) {
  errorMsg.value = e.message
  // 尝试从错误信息中提取位置信息
  errorPosition.value = getErrorPosition(inputText.value, e)
}

这种方法难以准确定位错误位置,特别是对于复杂的 JSON 结构。

解决方案:使用 jsonlint-mod

我们引入了 jsonlint-mod 库,它提供更详细的错误信息,包括准确的行号和列号:

import jsonlint from 'jsonlint-mod'

// 格式化 JSON
const format = () => {
  try {
    if (!inputText.value) return
    
    errorMsg.value = ''
    errorPosition.value = null
    
    try {
      const obj = jsonlint.parse(inputText.value)
      inputText.value = formatJsonPreserveUnicode(obj, 4)
      outputText.value = ''
    } catch (e) {
      const errorInfo = parseJsonlintError(e.message)
      errorPosition.value = {
        line: errorInfo.line,
        column: errorInfo.column
      }
      errorMsg.value = errorInfo.message
    }
  } catch (e) {
    errorMsg.value = e.message
  }
}

// 解析 jsonlint 错误信息
const parseJsonlintError = (errorMessage) => {
  const lineMatch = errorMessage.match(/line (\d+)/)
  const columnMatch = errorMessage.match(/column (\d+)/)
  
  return {
    line: lineMatch ? parseInt(lineMatch[1]) : 0,
    column: columnMatch ? parseInt(columnMatch[1]) : 0,
    message: errorMessage
  }
}

这样,我们就能准确显示 JSON 中的错误位置,并提供有用的错误提示信息。

3.3 Unicode 编码处理问题

在实现 JSON 格式化功能时,我们发现一个问题:当 JSON 中包含 Unicode 编码的中文字符时,格式化后这些字符被错误地转义了两次。

问题:Unicode 编码被双重转义

例如,原始 JSON 中的 "\u83b7\u53d6\u6210\u529f" 表示 Unicode 编码的中文字符串 “获取成功”,但格式化后变成了 "\\u83b7\\u53d6\\u6210\\u529f"

问题出在 JSON 解析和格式化的过程中:

  1. JSON.parse() 解析时会自动将 Unicode 编码转换为实际的中文字符
  2. JSON.stringify() 格式化时会将所有非 ASCII 字符(如中文)转换为 Unicode 编码
  3. 由于直接将结果赋值给文本框,所以显示的是转义后的形式
解决方案:自定义格式化函数

我们实现了一个自定义的 JSON 格式化函数,它能够保留原始的 Unicode 编码:

// 自定义 JSON 格式化函数,保留 Unicode 编码
const formatJsonPreserveUnicode = (json, indent = 4) => {
  let parsed
  if (typeof json === 'string') {
    parsed = JSON.parse(json)
  } else {
    parsed = json
  }
  
  // 使用正则表达式保留 Unicode 编码
  return JSON.stringify(parsed, null, indent)
    .replace(/\\\\u([0-9a-fA-F]{4})/g, '\\u$1')
}

这个函数确保在格式化和压缩 JSON 时,Unicode 编码的字符保持原样,不会被错误地转义两次。

3.4 Unicode 与中文互转功能

为了增强工具的实用性,我们添加了 Unicode 与中文互转功能:

// Unicode 转中文
const unicodeToChinese = () => {
  try {
    if (!inputText.value) return
    
    errorMsg.value = ''
    errorPosition.value = null
    
    // Unicode 转中文
    const result = inputText.value.replace(/\\u([0-9a-fA-F]{4})/g, (match, grp) => {
      return String.fromCharCode(parseInt(grp, 16))
    })
    
    // 结果直接显示在输入框中
    inputText.value = result
    // 清空输出文本,触发成功提示
    outputText.value = ''
  } catch (e) {
    errorMsg.value = e.message
  }
}

// 中文转 Unicode
const chineseToUnicode = () => {
  try {
    if (!inputText.value) return
    
    errorMsg.value = ''
    errorPosition.value = null
    
    // 中文转 Unicode
    const result = inputText.value.replace(/[\u4e00-\u9fa5]/g, (match) => {
      return '\\u' + match.charCodeAt(0).toString(16).padStart(4, '0')
    })
    
    // 结果直接显示在输入框中
    inputText.value = result
    // 清空输出文本,触发成功提示
    outputText.value = ''
  } catch (e) {
    errorMsg.value = e.message
  }
}

这两个功能使用正则表达式实现,能够准确地进行 Unicode 与中文的互相转换。

3.5 用户体验优化

为了提供更好的用户体验,我们实现了以下优化:

  1. 操作结果直接显示在输入框:所有操作(格式化、压缩、转义等)的结果直接显示在 JSON 文本框中,方便用户继续编辑。

  2. 成功提示:当操作成功时,在解析结果区域显示友好的成功提示:“老铁,这个JSON格式,没毛病。”

  3. 错误提示:当 JSON 格式有误时,显示详细的错误信息,包括错误行号、错误内容和期望的值类型。

  4. 复制功能:提供一键复制功能,方便用户复制处理后的 JSON 文本。

4. 遇到的问题及解决方案

4.1 滚动同步问题

问题:最初尝试使用两个独立的滚动区域,通过 JavaScript 同步滚动位置,但在不同平台上表现不一致。

解决方案:将行号和编辑区域放在同一个滚动容器内,利用 flex 布局实现并排显示,自然同步滚动。

4.2 行高对齐问题

问题:行号和文本内容的行高不一致,导致滚动时对不齐。

解决方案:为行号和编辑区域设置相同的行高和内边距,确保完美对齐。

.line-number, .json-editor {
  height: 42rpx;
  line-height: 42rpx;
}

4.3 错误定位问题

问题:使用浏览器内置的 JSON.parse() 难以准确定位错误位置。

解决方案:引入 jsonlint-mod 库,它提供更详细的错误信息,包括准确的行号和列号。

4.4 Unicode 编码双重转义问题

问题:JSON 中的 Unicode 编码在格式化后被错误地转义了两次。

解决方案:实现自定义的 JSON 格式化函数,确保 Unicode 编码保持原样。

4.5 跨平台兼容性问题

问题:不同平台(H5、小程序、App)对 DOM 操作和事件处理的支持不同。

解决方案:使用更简单的布局结构和更少的 JavaScript 代码,减少对平台特定 API 的依赖。

5. 总结

5.1 成功之处

  • 功能完善:实现了 JSON 格式化、压缩、转义、Unicode 转换等多种功能,满足了开发过程中的各种需求。
  • 用户体验好:提供了友好的界面、精确的错误提示和便捷的操作方式,提高了使用效率。
  • 跨平台兼容:通过精心设计的布局和代码,确保了在各平台上的一致表现。
  • 代码质量高:采用了 Vue 3 Composition API,代码结构清晰,易于维护和扩展。

5.2 经验教训

  • 从简单开始:在 UniApp 开发中,应该优先考虑简单的实现方式,避免过度依赖平台特定 API。
  • 减少 DOM 操作:尽量减少直接的 DOM 操作,特别是在跨平台场景下。
  • 利用布局特性:巧妙利用 CSS 布局特性可以解决许多看似复杂的问题。
  • 测试多平台:在开发过程中,应该在多个平台上测试,及早发现兼容性问题。
  • 注意细节:像 Unicode 编码这样的细节问题,可能会影响用户体验,需要特别注意。

5.3 未来改进

  • 添加更多功能:如 JSON 与 XML 互转、JSON 与 YAML 互转等。
  • 添加语法高亮:实现 JSON 语法高亮,提高可读性。
  • 优化性能:对大型 JSON 文件的处理性能进行优化。
  • 增加历史记录:添加操作历史记录功能,方便用户回退操作。
  • 支持文件导入导出:添加从文件导入和导出到文件的功能。

通过这个项目,我们不仅开发了一个实用的 JSON 工具,还积累了宝贵的 UniApp 跨平台开发经验,特别是在复杂 UI 交互和文本处理方面的实践经验,为未来的项目开发奠定了基础。

关于作者

如果本文章对您有所帮助,欢迎交流和探讨技术问题。
QQ: 313801120
更多文章: www.xiyueta.com/
希望能一起成长,共同探索更多开发技巧!


http://www.kler.cn/a/570493.html

相关文章:

  • 第十四届蓝桥杯:(二分算法)字串简写
  • 【MySQL】CAST()在MySQL中的用法以及其他常用的数据类型转换函数
  • 【部署】Docker Compose 指令备忘清单(超级详细!)
  • docker拉取乌班图并且ssh连接
  • C++小课堂——变量的声明,赋值和初始化
  • Redis是什么?如何使用Redis进行缓存操作?
  • Powershell和BTEQ工具实现带多组参数和标签的Teradata数据库批量数据导出程序
  • 深度学习-13.深度强化学习:深度 Q 学习
  • 【网络编程】之TCP通信步骤
  • 基础篇——深入解析SQL多表操作与关联查询:构建复杂数据关系的桥梁
  • 《解锁HarmonyOS NEXT高阶玩法:艺术图像识别功能开发全攻略》
  • Nginx将tomcat项目转发。将非80/443端口口转为80或443及https
  • halcon学习笔记1
  • Centos7部署k8s(单master节点安装)
  • 硅基流动前端如何设置tool工具
  • LINUX网络基础 - 网络编程套接字,UDP与TCP
  • 27、Java 反射机制
  • 数据结构(初阶)(五)----栈
  • 如何使用Python和SQLAlchemy结合外键映射来获取其他表中的数据
  • 迷你世界脚本组队接口:Team