企業(yè)網站托管搜索引擎優(yōu)化師
一、背景
之前在做錄制回放平臺的時候,需要前端展示子調用信息,子調用是一個請求列表數組結構,jsoneditor對數組的默認展示結構是[0].[1].[2]..的方式,為了達到如下的效果,必須用到 onNodeName的鉤子函數,因此深入調研了下vue3如何集成jsoneditor
最后做出來的效果圖
onNodeName的參考文檔 https://github.com/josdejong/jsoneditor/blob/master/docs/api.md
二、參考方案
json-editor-vue3 感謝這位老哥的方案,我看了下源碼,沒有滿足我的需要,核心就是屬性需要自己加,因此我拿著他的代碼改了下
三、代碼實現
-
安裝依賴 jsoneditor
npm?install?--save?jsoneditor
jsoneditor是個開源的js的組件,參考文檔 https://github.com/josdejong/jsoneditor
-
編寫組件
目錄結構如下
vue3-json-editor.tsx: 其中options的定義是完全參考jsoneditor的api文檔的,具體需要什么功能,自己去實現對應的options即可!
import?{?ComponentPublicInstance,?defineComponent,?getCurrentInstance,?onMounted,?reactive,?watch?}?from?'vue'
//?@ts-ignore
//?eslint-disable-next-line?import/extensions
import?JsonEditor?from?'jsoneditor';
import?'jsoneditor/dist/jsoneditor.min.css';
//?eslint-disable-next-line?import/prefer-default-export
export?const?Vue3JsonEditor?=?defineComponent({
??props:?{
????modelValue:?[String,?Boolean,?Object,?Array],
????showBtns:?[Boolean],
????expandedOnStart:?{
??????type:?Boolean,
??????default:?false
????},
????navigationBar:?{
??????type:?Boolean,
??????default:?true
????},
????mode:?{
??????type:?String,
??????default:?'tree'
????},
????modes:?{
??????type:?Array,
??????default?()?{
????????return?['tree',?'code',?'form',?'text',?'view']
??????}
????},
????lang:?{
??????type:?String,
??????default:?'en'
????},
????onNodeName:?{
??????type:?Function,
??????default:?()=>{}
????}
??},
??setup?(props:?any,?{?emit?})?{
????const?root?=?getCurrentInstance()?.root.proxy?as?ComponentPublicInstance
????const?state?=?reactive({
??????editor:?null?as?any,
??????error:?false,
??????json:?{},
??????internalChange:?false,
??????expandedModes:?['tree',?'view',?'form'],
??????uid:?`jsoneditor-vue-${getCurrentInstance()?.uid}`
????})
????watch(
??????()?=>?props.modelValue?as?unknown?as?any,
??????async?(val)?=>?{
????????if?(!state.internalChange)?{
??????????state.json?=?val
??????????//?eslint-disable-next-line?no-use-before-define
??????????await?setEditor(val)
??????????state.error?=?false
??????????//?eslint-disable-next-line?no-use-before-define
??????????expandAll()
????????}
??????},?{?immediate:?true?})
????onMounted(()?=>?{
??????//這個options的定義是完全參考jsoneditor的api文檔的
??????const?options?=?{
????????mode:?props.mode,
????????modes:?props.modes,
????????onChange?()?{
??????????try?{
????????????const?json?=?state.editor.get()
????????????state.json?=?json
????????????state.error?=?false
????????????//?eslint-disable-next-line?vue/custom-event-name-casing
????????????emit('json-change',?json)
????????????state.internalChange?=?true
????????????emit('input',?json)
????????????root.$nextTick(function?()?{
??????????????state.internalChange?=?false
????????????})
??????????}?catch?(e)?{
????????????state.error?=?true
????????????//?eslint-disable-next-line?vue/custom-event-name-casing
????????????emit('has-error',?e)
??????????}
????????},
????????onNodeName(v:?object)?{
??????????//?eslint-disable-next-line?vue/custom-event-name-casing
????????????return?props.onNodeName(v);
????????},
????????onModeChange?()?{
??????????//?eslint-disable-next-line?no-use-before-define
??????????expandAll()
????????},
????????navigationBar:?props.navigationBar
??????}
??????state.editor?=?new?JsonEditor(
????????document.querySelector(`#${state.uid}`),
????????options,
????????state.json
??????)
??????//?eslint-disable-next-line?vue/custom-event-name-casing
??????emit('provide-editor',?state.editor)
????})
????function?expandAll?()?{
??????if?(props.expandedOnStart?&&?state.expandedModes.includes(props.mode))?{
????????(state.editor?as?any).expandAll()
??????}
????}
????function?onSave?()?{
??????//?eslint-disable-next-line?vue/custom-event-name-casing
??????emit('json-save',?state.json)
????}
????function?setEditor?(value:?any):?void?{
??????if?(state.editor)?state.editor.set(value)
????}
????return?()?=>?{
??????//?@ts-ignore
??????//?@ts-ignore
??????return?(
????????<div>
??????????<div?id={state.uid}?class={'jsoneditor-vue'}></div>
????????</div>
??????)
????}
??}
})
style.css
.ace_line_group?{
??text-align:?left;
}
.json-editor-container?{
??display:?flex;
??width:?100%;
}
.json-editor-container?.tree-mode?{
??width:?50%;
}
.json-editor-container?.code-mode?{
??flex-grow:?1;
}
.jsoneditor-btns?{
??text-align:?center;
??margin-top:?10px;
}
.jsoneditor-vue?.jsoneditor-outer?{
??min-height:?150px;
}
.jsoneditor-vue?div.jsoneditor-tree?{
??min-height:?350px;
}
.json-save-btn?{
??background-color:?#20a0ff;
??border:?none;
??color:?#fff;
??padding:?5px?10px;
??border-radius:?5px;
??cursor:?pointer;
}
.json-save-btn:focus?{
??outline:?none;
}
.json-save-btn[disabled]?{
??background-color:?#1d8ce0;
??cursor:?not-allowed;
}
code?{
??background-color:?#f5f5f5;
}
index.ts
export?*?from?'./vue3-json-editor';
四、如何使用
<template>
??<div?class="container">
????<Vue3JsonEditor
????????v-model="json"
????????mode='view'
????????:show-btns="true"
????????:on-node-name="onNodeName"
????/>
??</div>
</template>
<script?lang="ts"?setup>
import?{computed,}?from?'vue'
import?{Vue3JsonEditor}?from?"@/components/json-editor";
const?props?=?defineProps({
??record:?{
????type:?Object,
????default()?{
??????return?{
????????request:?undefined,
??????};
????},
??},
});
const?json=computed(()=>{
??const?{record}?=?props;
??return?record.subInvocations;
});
//?eslint-disable-next-line?consistent-return
const?onNodeName?=?(node:?{
????value:?any;?type:?any
})=>{
??if?(node.type==='object'?&&?node.value.identity)?{
????return?node.value.identity;
??}
??return?undefined;
}
</script>
<script?lang="ts">
export?default?{
??name:?'Invocations',
};
</script>
<style?scoped?lang="less">
.container?{
??padding:?0?20px?20px?20px;
}
</style>
本文由 mdnice 多平臺發(fā)布