【功能新增】基于 https://github.com/josdejong/jsoneditor 二次封装 JsonEditor 组件,提供 JSON 编辑器功能

This commit is contained in:
puhui999
2025-03-28 13:54:16 +08:00
parent 7cb4c48d47
commit 6265d6d923
5 changed files with 225 additions and 29 deletions

View File

@ -0,0 +1,3 @@
import JsonEditor from './src/JsonEditor.vue'
export { JsonEditor }

View File

@ -0,0 +1,109 @@
<template>
<div ref="jsonEditorContainer" class="json-editor" :style="{ height }"></div>
</template>
<script setup lang="ts">
import { useVModel } from '@vueuse/core'
import { onBeforeUnmount, onMounted, ref, watch } from 'vue'
import JSONEditor, { JSONEditorMode, JSONEditorOptions } from 'jsoneditor'
import 'jsoneditor/dist/jsoneditor.min.css'
import { JsonEditorEmits, JsonEditorExpose, JsonEditorProps } from '../types'
/** 基于 https://github.com/josdejong/jsoneditor 二次封装组件,提供 JSON 编辑器功能。 */
defineOptions({ name: 'JsonEditor' })
const props = withDefaults(defineProps<JsonEditorProps>(), {
mode: 'tree' as JSONEditorMode,
height: '400px',
showModeSelection: false,
showNavigationBar: false,
showStatusBar: false,
showMainMenuBar: true
})
const emits = defineEmits<JsonEditorEmits>()
const jsonObj = useVModel(props, 'modelValue', emits) as Ref<any>
const jsonEditorContainer = ref<HTMLElement | null>(null)
let jsonEditor: JSONEditor | null = null
// 设置默认值
const height = props.height
// 初始化JSONEditor
const initJsonEditor = () => {
if (!jsonEditorContainer.value) return
// 合并默认配置和用户自定义配置
const options: JSONEditorOptions = {
mode: props.mode,
modes: props.showModeSelection
? (['tree', 'code', 'form', 'text', 'view', 'preview'] as JSONEditorMode[])
: undefined,
navigationBar: props.showNavigationBar,
statusBar: props.showStatusBar,
mainMenuBar: props.showMainMenuBar,
onChangeJSON: (json: any) => {
jsonObj.value = json
emits('change', json)
},
onValidationError: (errors: any) => {
emits('error', errors)
},
...props.options
} as JSONEditorOptions
// 创建JSONEditor实例
jsonEditor = new JSONEditor(jsonEditorContainer.value, options)
// 设置初始值
if (jsonObj.value) {
jsonEditor.set(jsonObj.value)
}
}
// 监听数据变化
watch(
() => jsonObj.value,
(newValue) => {
if (!jsonEditor) return
try {
// 防止无限循环更新
const currentJson = jsonEditor.get()
if (JSON.stringify(currentJson) !== JSON.stringify(newValue)) {
jsonEditor.update(newValue)
}
} catch (error) {
console.error('JSON更新失败:', error)
}
},
{ deep: true }
)
// 生命周期钩子
onMounted(() => {
initJsonEditor()
})
onBeforeUnmount(() => {
if (jsonEditor) {
jsonEditor.destroy()
jsonEditor = null
}
})
// 暴露方法
defineExpose<JsonEditorExpose>({
// 获取编辑器实例以便可以调用更多JSONEditor的原生方法
getEditor: () => jsonEditor
})
</script>
<style lang="scss" scoped>
/* 隐藏 Ace 编辑器的 powered by ace 标记 */
:deep(.jsoneditor-menu) {
/* 隐藏 powered by ace 标记 */
.jsoneditor-poweredBy {
display: none !important;
}
}
</style>

View File

@ -0,0 +1,80 @@
import { JSONEditorOptions, JSONEditorMode } from 'jsoneditor'
export interface JsonEditorProps {
/**
* JSON数据支持双向绑定
*/
modelValue: any
/**
* 编辑器模式
* @default 'tree'
*/
mode?: JSONEditorMode
/**
* 编辑器高度
* @default '400px'
*/
height?: string
/**
* 是否显示模式选择下拉菜单
* @default false
*/
showModeSelection?: boolean
/**
* 是否显示导航栏
* @default false
*/
showNavigationBar?: boolean
/**
* 是否显示状态栏
* @default true
*/
showStatusBar?: boolean
/**
* 是否显示主菜单栏
* @default true
*/
showMainMenuBar?: boolean
/**
* JSONEditor配置选项
* @see https://github.com/josdejong/jsoneditor/blob/develop/docs/api.md
*/
options?: Partial<JSONEditorOptions>
}
/**
* JsonEditor组件触发的事件
*/
export interface JsonEditorEmits {
/**
* 数据更新时触发
*/
(e: 'update:modelValue', value: any): void
/**
* 数据变化时触发
*/
(e: 'change', value: any): void
/**
* 验证错误时触发
*/
(e: 'error', errors: any): void
}
/**
* JsonEditor组件暴露的方法
*/
export interface JsonEditorExpose {
/**
* 获取原始的JSONEditor实例
*/
getEditor: () => any
}