React Native for OpenHarmony 实战:JSON格式化实现

今天我们用 React Native 实现一个 JSON 格式化工具,支持格式化、压缩、验证三种功能,还带有错误提示和动画效果。
状态设计
import React, { useState, useRef } from 'react';
import { View, Text, TextInput, TouchableOpacity, StyleSheet, ScrollView, Animated } from 'react-native';
export const JsonFormatter: React.FC = () => {
const [input, setInput] = useState('');
const [output, setOutput] = useState('');
const [error, setError] = useState('');
const buttonAnims = useRef([new Animated.Value(1), new Animated.Value(1), new Animated.Value(1)]).current;
const outputAnim = useRef(new Animated.Value(0)).current;
const shakeAnim = useRef(new Animated.Value(0)).current;
状态设计包含三个状态变量和三组动画值:
输入内容 input:存储用户输入的 JSON 字符串,初始为空。这是所有操作的数据源。
输出内容 output:存储处理后的结果,可能是格式化后的 JSON、压缩后的 JSON、或者验证结果。初始为空,只有在用户点击按钮后才会有内容。
错误信息 error:存储 JSON 解析失败时的错误信息,初始为空。如果 JSON 格式正确,这个状态保持为空;如果格式错误,显示具体的错误原因。
为什么要分开 output 和 error?因为它们是互斥的:要么显示输出结果,要么显示错误信息,不会同时显示。分开存储让逻辑更清晰,也方便条件渲染。
按钮动画数组 buttonAnims:三个按钮(格式化、压缩、验证)各有一个独立的动画值,初始都是 1(正常大小)。用数组字面量 [new Animated.Value(1), ...] 创建,比 Array(3).fill().map() 更简洁。
输出动画 outputAnim:输出区域的弹出动画,初始值 0(隐藏状态)。当有输出结果时,从 0 弹到 1,形成"弹出"效果。
抖动动画 shakeAnim:错误提示的抖动动画,初始值 0(静止状态)。当 JSON 格式错误时,错误框左右抖动,吸引用户注意。
这些动画值让工具更生动,不同的操作结果有不同的视觉反馈:成功时弹出输出,失败时抖动错误提示。
按钮动画函数
const animateButton = (index: number) => {
Animated.sequence([
Animated.timing(buttonAnims[index], { toValue: 0.9, duration: 100, useNativeDriver: true }),
Animated.spring(buttonAnims[index], { toValue: 1, friction: 3, useNativeDriver: true }),
]).start();
};
这个函数在用户点击按钮时触发,播放按钮的缩放动画。
动画序列的工作原理:
- 第一阶段:用
Animated.timing在 100 毫秒内把按钮缩小到 90%。这个阶段模拟"按下"的动作,按钮被压缩了。 - 第二阶段:用
Animated.spring弹回到原大小(100%)。friction: 3设置摩擦力,值越小弹性越大,按钮会有明显的"回弹"效果。
参数 index:指定要动画化的按钮索引(0=格式化,1=压缩,2=验证)。每个按钮有独立的动画值,点击哪个按钮就动画化哪个,互不干扰。
原生驱动:useNativeDriver: true 让动画在原生层执行,不占用 JavaScript 线程。即使主线程在解析 JSON(可能比较耗时),动画也能保持流畅。
这个动画给用户即时反馈:“我点击了这个按钮,操作正在执行”。即使 JSON 解析需要几毫秒,用户也不会感觉到延迟,因为动画立即开始了。
输出动画函数
const showOutput = () => {
outputAnim.setValue(0);
Animated.spring(outputAnim, { toValue: 1, friction: 5, useNativeDriver: true }).start();
};
这个函数在操作成功时触发,播放输出区域的弹出动画。
重置动画值:outputAnim.setValue(0) 把动画值重置为 0(隐藏状态)。为什么要重置?因为用户可能多次点击按钮,每次都应该有弹出效果。如果不重置,第二次点击时动画值已经是 1,就不会有动画了。
弹簧动画:从 0 弹到 1,friction: 5 设置摩擦力。摩擦力比按钮动画大(5 vs 3),弹性稍弱,动画更稳定。输出区域比按钮大,如果弹性太强,会显得很夸张。
视觉效果:输出区域从无到有,伴随缩放和透明度变化(后面会看到),给用户"结果已生成"的明确反馈。
错误动画函数
const showError = () => {
Animated.sequence([
Animated.timing(shakeAnim, { toValue: 1, duration: 50, useNativeDriver: true }),
Animated.timing(shakeAnim, { toValue: -1, duration: 50, useNativeDriver: true }),
Animated.timing(shakeAnim, { toValue: 1, duration: 50, useNativeDriver: true }),
Animated.timing(shakeAnim, { toValue: 0, duration: 50, useNativeDriver: true }),
]).start();
};
这个函数在 JSON 格式错误时触发,播放错误框的抖动动画。
抖动序列:四个阶段,每个阶段 50 毫秒,总共 200 毫秒:
- 向右旋转(0 → 1)
- 向左旋转(1 → -1)
- 再向右旋转(-1 → 1)
- 回到中心(1 → 0)
为什么用旋转而不是平移?因为旋转更引人注意。平移只是左右移动,旋转会让整个错误框"摇晃",像是在说"不对不对"。这种拟人化的动画更容易被用户注意到。
时长选择:50 毫秒很短,抖动很快,给人"紧急"的感觉。如果用 200 毫秒,抖动会很慢,像是在"摇摆",不够紧迫。
视觉效果:错误框快速左右摇晃,吸引用户注意。配合红色背景和边框,让用户立即知道"出错了"。
格式化函数
const format = () => {
animateButton(0);
try {
const obj = JSON.parse(input);
setOutput(JSON.stringify(obj, null, 2));
setError('');
showOutput();
} catch (e: any) {
setError('JSON格式错误: ' + e.message);
setOutput('');
showError();
}
};
格式化是最常用的功能,把压缩的 JSON 转换成易读的格式。
执行流程:
animateButton(0):触发第一个按钮(格式化)的动画JSON.parse(input):解析 JSON 字符串,转换成 JavaScript 对象JSON.stringify(obj, null, 2):把对象转回 JSON 字符串,带缩进setOutput(...):更新输出状态setError(''):清空错误信息(如果之前有错误)showOutput():触发输出区域的弹出动画
JSON.stringify 的参数:
- 第一个参数:要转换的对象
- 第二个参数:
null表示不过滤属性(保留所有属性) - 第三个参数:
2表示缩进 2 个空格
比如输入 {"name":"John","age":30},输出:
{
"name": "John",
"age": 30
}
错误处理:如果 JSON.parse 失败(JSON 格式错误),会抛出异常。catch 捕获异常,提取错误信息(e.message),显示给用户。同时清空输出(setOutput('')),触发错误动画。
为什么先动画再解析?因为动画是同步的(立即开始),解析是可能耗时的(大 JSON 可能需要几毫秒)。先动画让用户立即看到反馈,不会感觉到延迟。
压缩函数
const minify = () => {
animateButton(1);
try {
const obj = JSON.parse(input);
setOutput(JSON.stringify(obj));
setError('');
showOutput();
} catch (e: any) {
setError('JSON格式错误: ' + e.message);
setOutput('');
showError();
}
};
压缩功能把格式化的 JSON 转换成紧凑格式,去除所有空白字符。
和格式化的区别:只有一个地方不同——JSON.stringify(obj) 只传一个参数,不传缩进参数。这样生成的 JSON 没有换行和缩进,所有内容在一行。
比如输入:
{
"name": "John",
"age": 30
}
输出:{"name":"John","age":30}
使用场景:
- 减小体积:去除空白字符可以减小 JSON 的体积,节省网络传输和存储空间
- API 传输:发送给服务器的 JSON 通常是压缩的,不需要格式化
- 配置文件:某些配置文件要求紧凑格式
错误处理:和格式化函数完全一样,如果 JSON 格式错误,显示错误信息并触发抖动动画。
验证函数
const validate = () => {
animateButton(2);
try {
JSON.parse(input);
setError('');
setOutput('✅ JSON格式正确');
showOutput();
} catch (e: any) {
setError('❌ ' + e.message);
setOutput('');
showError();
}
};
验证功能只检查 JSON 格式是否正确,不输出转换结果。
执行流程:
animateButton(2):触发第三个按钮(验证)的动画JSON.parse(input):尝试解析 JSON- 如果成功:显示"✅ JSON格式正确",触发输出动画
- 如果失败:显示"❌ 错误信息",触发错误动画
为什么不输出解析结果?因为验证的目的是检查格式,不是转换数据。用户只需要知道"对"或"错",不需要看到转换后的 JSON。
emoji 的使用:✅ 和 ❌ 是通用的符号,不需要解释就能理解。绿色的勾表示成功,红色的叉表示失败,直观易懂。
使用场景:
- 快速检查:不确定 JSON 格式是否正确,快速验证一下
- 调试 API:API 返回的数据格式不对,用验证功能找出错误位置
- 学习 JSON:初学者不确定自己写的 JSON 是否正确,用验证功能检查
抖动动画插值
const shake = shakeAnim.interpolate({
inputRange: [-1, 0, 1],
outputRange: ['-3deg', '0deg', '3deg'],
});
interpolate 把动画值映射成旋转角度:
- 动画值 -1 → 旋转 -3 度(向左)
- 动画值 0 → 旋转 0 度(正中)
- 动画值 1 → 旋转 3 度(向右)
角度选择:3 度是一个很微妙的角度,足以让用户注意到抖动,但不会太夸张。如果用 10 度,错误框会剧烈摇晃,像是要翻倒了;如果用 1 度,抖动太小,可能注意不到。
为什么用度数而不是弧度?因为度数更直观,3 度大概是 5% 的倾斜,人类更容易理解。弧度(0.05 rad)对大多数人来说没有直观感受。
这个插值会应用到错误框的 transform: [{ rotate: shake }],让错误框左右旋转。
鸿蒙 ArkTS 对比:JSON 处理
format() {
this.animateButton(0)
try {
const obj = JSON.parse(this.input)
this.output = JSON.stringify(obj, null, 2)
this.error = ''
this.showOutput()
} catch (e) {
this.error = 'JSON格式错误: ' + e.message
this.output = ''
this.showError()
}
}
minify() {
this.animateButton(1)
try {
const obj = JSON.parse(this.input)
this.output = JSON.stringify(obj)
this.error = ''
this.showOutput()
} catch (e) {
this.error = 'JSON格式错误: ' + e.message
this.output = ''
this.showError()
}
}
validate() {
this.animateButton(2)
try {
JSON.parse(this.input)
this.error = ''
this.output = '✅ JSON格式正确'
this.showOutput()
} catch (e) {
this.error = '❌ ' + e.message
this.output = ''
this.showError()
}
}
ArkTS 中的 JSON 处理逻辑完全一样,因为 JSON.parse 和 JSON.stringify 是 JavaScript 标准 API,跨平台通用。这就是 React Native 的优势——核心业务逻辑可以直接复用,不需要为每个平台重写。
界面渲染:头部和输入框
return (
<ScrollView style={styles.container}>
<View style={styles.header}>
<Text style={styles.headerIcon}>📋</Text>
<Text style={styles.headerTitle}>JSON 格式化</Text>
<Text style={styles.headerSubtitle}>格式化、压缩、验证JSON</Text>
</View>
<View style={styles.inputCard}>
<Text style={styles.label}>输入JSON</Text>
<TextInput
style={styles.input}
value={input}
onChangeText={setInput}
multiline
placeholder='{"key": "value"}'
placeholderTextColor="#666"
/>
</View>
头部区域包含图标、标题、副标题,和其他工具保持一致的风格。📋 剪贴板图标表示"数据"的概念,和 JSON 的用途相符。
输入框设计:
- 标签"输入JSON"明确告诉用户这里应该输入什么
multiline让输入框支持多行输入,因为 JSON 通常是多行的placeholder提供一个简单的 JSON 示例,让用户知道格式placeholderTextColor="#666"设置占位符颜色为灰色,和实际输入的青蓝色文本形成对比
为什么用等宽字体?后面的样式中,输入框用了 fontFamily: 'monospace'(等宽字体)。等宽字体让 JSON 的结构更清晰,每个字符占据相同宽度,缩进对齐更明显。这是代码编辑器的标准做法。
颜色选择:输入框的文本颜色是 #9cdcfe(青蓝色),这是 VS Code 中字符串的颜色。程序员看到这个颜色会觉得很熟悉,有"在写代码"的感觉。
按钮渲染
<View style={styles.btnRow}>
{[
{ text: '格式化', icon: '✨', onPress: format },
{ text: '压缩', icon: '📦', onPress: minify },
{ text: '验证', icon: '✅', onPress: validate },
].map((btn, i) => (
<Animated.View key={i} style={[styles.btnWrapper, { transform: [{ scale: buttonAnims[i] }] }]}>
<TouchableOpacity style={styles.btn} onPress={btn.onPress} activeOpacity={0.8}>
<Text style={styles.btnIcon}>{btn.icon}</Text>
<Text style={styles.btnText}>{btn.text}</Text>
</TouchableOpacity>
</Animated.View>
))}
</View>
三个按钮横向排列,用数组字面量定义按钮数据,map 遍历生成按钮。
按钮数据结构:每个按钮包含文字、图标、点击处理函数。这种数据驱动的设计让代码很简洁,如果要添加新按钮,只需要在数组里加一项。
图标选择:
- ✨ 星星表示"美化",格式化让 JSON 变漂亮
- 📦 盒子表示"打包",压缩让 JSON 变紧凑
- ✅ 勾号表示"检查",验证检查格式是否正确
这些 emoji 的含义很直观,不需要解释就能理解。
动画包裹:每个按钮用 Animated.View 包裹,应用独立的缩放动画。key={i} 用索引作为 key,因为按钮的顺序和数量是固定的,不会变化。
横向布局:flexDirection: 'row' 让三个按钮横向排列,flex: 1 让它们平均分配宽度。无论屏幕多宽,三个按钮总是等宽的。
点击处理:onPress={btn.onPress} 直接传入处理函数,不需要包装。因为处理函数已经定义好了(format、minify、validate),直接传入即可。
触摸反馈:activeOpacity={0.8} 让按钮按下时稍微变暗,配合缩放动画,给用户双重反馈。
错误提示渲染
{error ? (
<Animated.View style={[styles.errorBox, { transform: [{ rotate: shake }] }]}>
<Text style={styles.errorText}>{error}</Text>
</Animated.View>
) : null}
错误提示只在有错误时才显示,用条件渲染实现。
条件渲染:error ? 检查错误信息是否为空。如果为空(空字符串是 falsy),返回 null,不渲染任何内容;如果不为空,渲染错误框。
抖动动画:transform: [{ rotate: shake }] 应用旋转动画。shake 是前面定义的插值,会在 -3 度到 3 度之间变化。
错误框样式:红色背景(半透明)、红色边框、红色文字,三重红色让用户立即知道"出错了"。半透明背景(rgba(231, 76, 60, 0.2))不会太刺眼,但足够醒目。
错误信息:直接显示 JSON.parse 抛出的错误信息,比如 "Unexpected token } in JSON at position 10"。这些信息虽然是英文,但对程序员来说很有用,能快速定位错误位置。
输出区域渲染
{output ? (
<Animated.View style={[styles.outputCard, {
transform: [{ scale: outputAnim }, { perspective: 1000 }],
opacity: outputAnim,
}]}>
<Text style={styles.label}>输出</Text>
<View style={styles.outputBox}>
<Text style={styles.output} selectable>{output}</Text>
</View>
</Animated.View>
) : null}
</ScrollView>
);
};
输出区域只在有输出时才显示,用条件渲染实现。
条件渲染:output ? 检查输出内容是否为空。如果为空,返回 null;如果不为空,渲染输出卡片。
弹出动画:同时应用缩放和透明度动画:
scale: outputAnim:从 0 到 1,卡片从无到有opacity: outputAnim:从 0 到 1,卡片从透明到不透明perspective: 1000:添加 3D 透视,让缩放动画更有立体感
为什么同时用缩放和透明度?因为单独用缩放,卡片会从一个点突然出现,有点突兀;单独用透明度,卡片会原地淡入,不够生动。两者结合,卡片从小到大、从透明到不透明,形成"弹出"效果,更自然。
可选择文本:selectable 属性让用户可以长按选择复制输出内容。这是一个很重要的功能,用户格式化 JSON 后通常需要复制结果,如果不能复制,就得手动输入,体验很差。
等宽字体:输出文本也用等宽字体(fontFamily: 'monospace'),让 JSON 的结构清晰。格式化后的 JSON 有缩进,等宽字体让缩进对齐,易于阅读。
颜色选择:输出文本用青蓝色(#9cdcfe),和输入框一致。输出框的背景色(#1e1e1e)比输入框更深,这是 VS Code 的深色主题配色,程序员看着很舒服。
鸿蒙 ArkTS 对比:界面渲染
Column() {
// 头部
Column() {
Text('📋').fontSize(50).margin({ bottom: 8 })
Text('JSON 格式化').fontSize(28).fontWeight(FontWeight.Bold).fontColor(Color.White)
Text('格式化、压缩、验证JSON').fontSize(14).fontColor('#888888').margin({ top: 4 })
}
.width('100%')
.alignItems(HorizontalAlign.Center)
.margin({ bottom: 24 })
// 输入框
Column() {
Text('输入JSON').fontSize(14).fontColor('#888888').margin({ bottom: 12 })
TextArea({ text: this.input, placeholder: '{"key": "value"}' })
.width('100%')
.height(150)
.backgroundColor('#252550')
.fontColor('#9cdcfe')
.fontFamily('monospace')
.onChange((value: string) => {
this.input = value
})
}
.width('100%')
.backgroundColor('#1a1a3e')
.borderRadius(20)
.padding(20)
// 按钮
Row() {
ForEach([
{ text: '格式化', icon: '✨', action: () => this.format() },
{ text: '压缩', icon: '📦', action: () => this.minify() },
{ text: '验证', icon: '✅', action: () => this.validate() },
], (btn: ButtonItem, index: number) => {
Button() {
Row() {
Text(btn.icon).fontSize(16).margin({ right: 6 })
Text(btn.text).fontWeight(FontWeight.Medium)
}
}
.layoutWeight(1)
.backgroundColor('#4A90D9')
.onClick(btn.action)
.scale({ x: this.buttonScales[index], y: this.buttonScales[index] })
})
}
.width('100%')
// 错误提示
if (this.error) {
Column() {
Text(this.error).fontColor('#e74c3c')
}
.width('100%')
.backgroundColor('rgba(231, 76, 60, 0.2)')
.borderRadius(12)
.padding(16)
.border({ width: 1, color: '#e74c3c' })
.rotate({ angle: this.shakeAngle })
}
// 输出
if (this.output) {
Column() {
Text('输出').fontSize(14).fontColor('#888888').margin({ bottom: 12 })
Column() {
Text(this.output)
.fontColor('#9cdcfe')
.fontFamily('monospace')
.fontSize(12)
.copyOption(CopyOptions.LocalDevice)
}
.width('100%')
.backgroundColor('#1e1e1e')
.borderRadius(12)
.padding(16)
}
.width('100%')
.backgroundColor('#1a1a3e')
.borderRadius(20)
.padding(20)
.scale({ x: this.outputScale, y: this.outputScale })
.opacity(this.outputOpacity)
}
}
鸿蒙的布局结构和 React Native 类似,只是语法不同。Column 对应垂直布局,Row 对应水平布局,TextArea 对应多行输入框。条件渲染用 if 语句,动画用 scale、rotate、opacity 属性。
核心逻辑(JSON 处理、错误处理)完全一样,只是界面代码需要适配鸿蒙的组件和 API。
样式定义:容器和头部
const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: '#0f0f23', padding: 20 },
header: { alignItems: 'center', marginBottom: 24 },
headerIcon: { fontSize: 50, marginBottom: 8 },
headerTitle: { fontSize: 28, fontWeight: '700', color: '#fff' },
headerSubtitle: { fontSize: 14, color: '#888', marginTop: 4 },
容器用深蓝色背景 #0f0f23,这是整个应用的统一配色。padding: 20 在四周留出边距,让内容不会紧贴屏幕边缘。
头部元素全部居中对齐,图标、标题、副标题垂直排列,形成清晰的视觉层次。字号从大到小(50 → 28 → 14),颜色从亮到暗(emoji → 白色 → 灰色),引导用户的视线从上到下阅读。
样式定义:输入框
inputCard: {
backgroundColor: '#1a1a3e',
borderRadius: 20,
padding: 20,
marginBottom: 20,
borderWidth: 1,
borderColor: '#3a3a6a',
},
label: { color: '#888', fontSize: 14, marginBottom: 12 },
input: {
backgroundColor: '#252550',
padding: 16,
borderRadius: 12,
minHeight: 150,
color: '#9cdcfe',
fontSize: 14,
fontFamily: 'monospace',
},
输入框卡片用深蓝色背景,圆角 20,内边距 20,边框颜色比背景稍亮,形成立体感。
标签样式:灰色文字,14 号字体,下边距 12。标签的作用是说明输入框的用途,不需要太醒目,灰色刚好。
输入框样式:
- 背景色
#252550比卡片背景更深,让用户知道"这是可以输入的区域" - 文字颜色
#9cdcfe是青蓝色,这是 VS Code 中字符串的颜色,程序员看着很熟悉 - 字号 14,比普通文本稍小,因为 JSON 通常内容较多,小字号可以显示更多内容
fontFamily: 'monospace'使用等宽字体,让 JSON 的结构更清晰
为什么用等宽字体?因为 JSON 的缩进很重要,等宽字体让每个字符占据相同宽度,缩进对齐更明显。比如:
{
"name": "John",
"age": 30
}
如果用比例字体(proportional font),"name" 和 "age" 的宽度不同,缩进看起来不对齐。等宽字体让所有字符宽度相同,缩进完美对齐。
样式定义:按钮
btnRow: { flexDirection: 'row', marginBottom: 20 },
btnWrapper: { flex: 1, marginHorizontal: 4 },
btn: {
backgroundColor: '#4A90D9',
padding: 14,
borderRadius: 12,
alignItems: 'center',
flexDirection: 'row',
justifyContent: 'center',
},
btnIcon: { fontSize: 16, marginRight: 6 },
btnText: { color: '#fff', fontWeight: '600' },
按钮行用横向布局,三个按钮平均分配宽度。
按钮包裹器:flex: 1 让三个按钮等宽,marginHorizontal: 4 在按钮之间留出 8 像素的间距(左右各 4)。
按钮样式:
- 蓝色背景
#4A90D9,这是应用的主题色,用于所有主要操作按钮 - 内边距 14,让按钮有足够的点击区域
- 圆角 12,和卡片的圆角一致
flexDirection: 'row'让图标和文字横向排列justifyContent: 'center'和alignItems: 'center'让内容居中
按钮内容:
- 图标 16 号字体,文字默认字体(通常是 14-16)
- 图标和文字之间留 6 像素间距
- 文字用中等粗细(
fontWeight: '600'),比正常文字粗一点
为什么按钮用蓝色而不是深色?因为按钮是主要操作,需要突出显示。如果用深色(和卡片一样),按钮会"淹没"在背景中,不够醒目。蓝色在深色背景上很显眼,而且给人"可点击"的感觉。
样式定义:错误提示和输出
errorBox: {
backgroundColor: 'rgba(231, 76, 60, 0.2)',
borderRadius: 12,
padding: 16,
marginBottom: 20,
borderWidth: 1,
borderColor: '#e74c3c',
},
errorText: { color: '#e74c3c' },
outputCard: {
backgroundColor: '#1a1a3e',
borderRadius: 20,
padding: 20,
borderWidth: 1,
borderColor: '#3a3a6a',
},
outputBox: {
backgroundColor: '#1e1e1e',
padding: 16,
borderRadius: 12,
minHeight: 150,
},
output: { color: '#9cdcfe', fontFamily: 'monospace', fontSize: 12 },
});
错误框样式:
- 背景色
rgba(231, 76, 60, 0.2)是半透明的红色,不会太刺眼,但足够醒目 - 边框颜色
#e74c3c是不透明的红色,和背景形成对比 - 文字颜色也是红色,三重红色让用户立即知道"出错了"
为什么用半透明背景?因为纯红色背景太刺眼,会让用户感到不舒服。半透明背景(20% 不透明度)柔和很多,但仍然能引起注意。这是一个常见的 UI 设计技巧。
输出卡片样式:
- 和输入卡片一样的背景色、圆角、边框,保持视觉一致性
- 输出框的背景色
#1e1e1e比输入框更深,这是 VS Code 的深色主题配色 - 输出文字用等宽字体,字号 12,比输入框稍小
为什么输出文字更小?因为格式化后的 JSON 通常比输入的 JSON 长(增加了换行和缩进),用小字号可以在同样的空间里显示更多内容。而且输出是只读的,不需要编辑,小字号不会影响使用。
颜色一致性:输入框和输出框都用青蓝色文字(#9cdcfe)、等宽字体,让用户感觉它们是"配套"的。输入和输出在视觉上形成呼应,用户一眼就能看出它们的关系。
小结
这个 JSON 格式化工具展示了 JavaScript 内置 API 的强大。JSON.parse 和 JSON.stringify 两个函数就能实现格式化、压缩、验证三种功能。错误处理用 try-catch 捕获异常,显示具体的错误信息。按钮的缩放动画、输出的弹出动画、错误的抖动动画,不同的操作结果有不同的视觉反馈。在 OpenHarmony 平台上,JSON.parse 和 JSON.stringify 是 JavaScript 标准 API,跨平台通用。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)