一个支持 JSONC(允许注释、尾随逗号)的 JSON 文本编辑器,基于 vue-codemirror
与 @codemirror/lint
,内置语法校验与一键格式化。
项目已内置依赖,外部项目使用时请确保安装:
pnpm add vue-codemirror @codemirror/lang-json @codemirror/language @codemirror/view @codemirror/state @codemirror/lint jsonc-parser @iconify/vue @iconify-icons/ri
<script setup lang="ts">
import { ref } from 'vue';
import JsonTextEditor from '@/components/JsonTextEditor/index.vue';
const value = ref('{"name":"小红"}');
</script>
<template>
<JsonTextEditor v-model="value" height="300px" />
<!-- disabled -->
<JsonTextEditor v-model="value" :disabled="true" />
</template>
- modelValue? string: 绑定的字符串值,内容可包含注释与尾随逗号(JSONC)。
- height? string: 编辑器高度,默认
400px
,如"300px"
、"50vh"
。 - disabled? boolean: 是否禁用,仅展示不可编辑态。
- update:modelValue(value: string): 内容变化时触发,返回最新字符串。
- 语法校验: 实时 lint,错误会在编辑器中以错误标记显示,并附带修复建议。
- 允许注释/尾随逗号: 使用
jsonc-parser
解析;错误提示对常见问题(缺逗号、无效符号、引号不匹配等)有友好信息与建议。 - 格式化: 支持两种触发方式:
- 失焦时自动格式化(
blur
)。 - 点击右上角格式化按钮手动格式化。
- 失焦时自动格式化(
组件通过 defineExpose
暴露以下方法:
- hasError(): boolean: 当前内容是否存在语法问题(基于 JSONC 校验)。
- getJsonValue(): any: 解析并返回对象/数组值(JSONC 解析出包含注释时的 JSON 对象)。
使用示例:
<script setup lang="ts">
import { ref } from 'vue';
import JsonTextEditor from '@/components/JsonTextEditor/index.vue';
const value = ref('{"name":"小红","age":13}');
const editorRef = ref<any>(null);
function submit() {
if (editorRef.value?.hasError()) {
// 有错误时阻止提交
return;
}
const data = editorRef.value?.getJsonValue();
console.log('提交数据:', data);
}
</script>
<template>
<JsonTextEditor ref="editorRef" v-model="value" height="320px" />
<button @click="submit">提交</button>
<pre>{{ value }}</pre>
<!-- 如果你想在控制台看到字面量的 \n,而不是换行,可: -->
<!-- console.log(JSON.stringify(String(value))) -->
</template>
-
如何显示字面量的换行符
\n
?- 在控制台打印时用:
JSON.stringify(String(value))
,即可看到\n
而非实际换行。
- 在控制台打印时用:
-
如何仅允许查看不允许编辑?
- 传入
:disabled="true"
。
- 传入
-
最后一行缺少逗号/引号等常见错误会提示吗?
- 会。组件内置的 Lint 会给出错误位置与建议信息。
<template>
<div style="padding:16px">
<JsonTextEditor v-model="value" height="300px" />
</div>
<pre>{{ value }}</pre>
<button @click="log">Log</button>
<button @click="check">Check</button>
<button @click="parse">Parse</button>
<JsonTextEditor v-model="value" :disabled="true" height="200px" />
<!-- 错误示例,便于观察提示 -->
<JsonTextEditor v-model="errorVal" height="200px" />
<!-- disabled 示例 -->
<JsonTextEditor v-model="value" height="200px" :disabled="true" />
<!-- 提示:失焦或点按钮会自动格式化 -->
<script setup lang="ts">
import { ref } from 'vue';
import JsonTextEditor from '@/components/JsonTextEditor/index.vue';
const value = ref(`{
// 在学校的情况信息
"name": "小红",
"age": 13,
"school": {
"class": "一班",
"num": 1,
"position": "班长"
}
}`);
const errorVal = ref(`{
"name": "小明",
"family": {
"home": "中国",
"mother": "红妈",
},
"age"
}`);
const editorRef = ref<any>(null);
function log() {
console.log(JSON.stringify(String(value.value)));
}
function check() {
alert(editorRef.value?.hasError() ? '存在语法错误' : '语法正确');
}
function parse() {
try {
console.log('parsed:', editorRef.value?.getJsonValue());
} catch (e) {
console.error(e);
}
}
</script>
组件自带基础样式(边框、禁用态、格式化按钮位置等),可在外层容器中自定义宽高与布局,无需额外样式依赖。
仅供学习与内部使用。根据实际需要调整依赖与样式。