diff --git a/example/App.tsx b/example/App.tsx index 76b027a..1715988 100644 --- a/example/App.tsx +++ b/example/App.tsx @@ -37,6 +37,9 @@ export default defineComponent({ const onActiveChange = (key: string) => { state.activeKey = key; + if (!state.opened.includes(key)) { + state.opened.push(key); + } }; return { diff --git a/example/Basic.vue b/example/Basic.vue index 9f1655b..4bfde82 100644 --- a/example/Basic.vue +++ b/example/Basic.vue @@ -18,6 +18,10 @@ +
+ + +
@@ -58,9 +62,11 @@ :show-double-quotes="state.showDoubleQuotes" :show-length="state.showLength" :show-line="state.showLine" + :show-line-number="state.showLineNumber" :collapsed-on-click-brackets="state.collapsedOnClickBrackets" :custom-value-formatter="state.useCustomLinkFormatter ? customLinkFormatter : null" :show-icon="state.showIcon" + style="position: relative" />
@@ -85,9 +91,6 @@ const defaultData = { 'Traffic paradise: How to design streets for people and unmanned vehicles in the future?', source: 'Netease smart', link: 'http://netease.smart/traffic-paradise/1235', - author: { - names: ['Daniel', 'Mike', 'John'], - }, }, { news_id: 51182, @@ -110,6 +113,7 @@ export default defineComponent({ data: defaultData, showLength: false, showLine: true, + showLineNumber: false, showDoubleQuotes: true, collapsedOnClickBrackets: true, useCustomLinkFormatter: false, diff --git a/example/Editable.vue b/example/Editable.vue index 04cd41f..97bf547 100644 --- a/example/Editable.vue +++ b/example/Editable.vue @@ -15,8 +15,8 @@
- - + +
@@ -44,9 +44,10 @@ @@ -85,7 +86,7 @@ const defaultData = { }; export default defineComponent({ - name: 'SelectControl', + name: 'Editable', components: { VueJsonPretty, }, @@ -95,7 +96,7 @@ export default defineComponent({ data: defaultData, showLength: false, showLine: true, - showDoubleQuotes: true, + showLineNumber: false, editable: true, editableTrigger: 'click', deep: 3, diff --git a/example/SelectControl.vue b/example/SelectControl.vue index 3a57111..87c551d 100644 --- a/example/SelectControl.vue +++ b/example/SelectControl.vue @@ -6,6 +6,10 @@

Options:

+
+ + +
- - + +
@@ -53,10 +57,6 @@
-
- - -

v-model:selectedValue:

{{ state.selectedValue }}
@@ -75,16 +75,17 @@ :data="state.data" :path="state.path" :deep="state.deep" - :show-double-quotes="state.showDoubleQuotes" + :show-double-quotes="true" :highlight-selected-node="state.highlightSelectedNode" :show-length="state.showLength" :show-line="state.showLine" + :show-line-number="state.showLineNumber" :select-on-click-node="state.selectOnClickNode" :collapsed-on-click-brackets="state.collapsedOnClickBrackets" :path-selectable="(path, data) => typeof state.data !== 'number'" :selectable-type="state.selectableType" :show-select-controller="state.showSelectController" - :custom-value-formatter="state.useCustomLinkFormatter ? customLinkFormatter : null" + :show-icon="state.showIcon" @nodeClick="handleClick" @selectedChange="handleChange" /> @@ -137,15 +138,15 @@ export default defineComponent({ showSelectController: true, showLength: false, showLine: true, - showDoubleQuotes: true, + showLineNumber: false, highlightSelectedNode: true, selectOnClickNode: true, collapsedOnClickBrackets: true, - useCustomLinkFormatter: false, path: 'res', deep: 3, itemData: {}, itemPath: '', + showIcon: false, }); const handleClick = (path, data) => { @@ -158,14 +159,6 @@ export default defineComponent({ // console.log('newVal: ', newVal, ' oldVal: ', oldVal); }; - const customLinkFormatter = (data, key, path, defaultFormatted) => { - if (typeof data === 'string' && data.startsWith('http://')) { - return `"${data}"`; - } else { - return defaultFormatted; - } - }; - watch( () => state.val, newVal => { @@ -192,18 +185,8 @@ export default defineComponent({ }, ); - watch( - () => state.useCustomLinkFormatter, - async () => { - state.renderOK = false; - await nextTick(); - state.renderOK = true; - }, - ); - return { state, - customLinkFormatter, handleClick, handleChange, }; diff --git a/src/components/Tree/index.tsx b/src/components/Tree/index.tsx index d2302a4..8774d0b 100644 --- a/src/components/Tree/index.tsx +++ b/src/components/Tree/index.tsx @@ -1,4 +1,12 @@ -import { defineComponent, reactive, computed, watchEffect, ref, PropType } from 'vue'; +import { + defineComponent, + reactive, + computed, + watchEffect, + ref, + PropType, + CSSProperties, +} from 'vue'; import TreeNode, { treeNodePropsPass, NodeDataType } from 'src/components/TreeNode'; import { emitError, jsonFlatten, JSONDataType, cloneDeep } from 'src/utils'; import './styles.less'; @@ -54,6 +62,7 @@ export default defineComponent({ type: [String, Array] as PropType, default: () => '', }, + style: Object as PropType, }, emits: ['nodeClick', 'bracketsClick', 'selectedChange', 'update:selectedValue', 'update:data'], @@ -98,8 +107,9 @@ export default defineComponent({ if (startHiddenItem && startHiddenItem.path === item.path) { const isObject = startHiddenItem.type === 'objectStart'; const mergeItem = { - ...startHiddenItem, ...item, + ...startHiddenItem, + showComma: item.showComma, content: isObject ? '{...}' : '[...]', type: isObject ? 'objectCollapsed' : 'arrayCollapsed', } as NodeDataType; @@ -203,7 +213,6 @@ export default defineComponent({ const rootPath = props.path; new Function('data', 'val', `data${path.slice(rootPath.length)}=val`)(newData, value); emit('update:data', newData); - console.log(newData); }; watchEffect(() => { @@ -240,6 +249,7 @@ export default defineComponent({ showDoubleQuotes, showLength, showLine, + showLineNumber, showSelectController, selectOnClickNode, pathSelectable, @@ -252,6 +262,7 @@ export default defineComponent({ editable, editableTrigger, showIcon, + style, } = this; const { onTreeNodeClick, onBracketsClick, onSelectedChange, onTreeScroll, onValueChange } = @@ -271,6 +282,7 @@ export default defineComponent({ checked={selectedPaths.includes(item.path)} selectable-type={selectableType} show-line={showLine} + show-line-number={showLineNumber} show-select-controller={showSelectController} select-on-click-node={selectOnClickNode} path-selectable={pathSelectable} @@ -293,7 +305,12 @@ export default defineComponent({ 'vjs-tree': true, 'is-virtual': virtual, }} - onScroll={virtual ? onTreeScroll: undefined} + onScroll={virtual ? onTreeScroll : undefined} + style={ + showLineNumber + ? { paddingLeft: `${Number(flatData.length.toString().length) * 12}px`, ...style } + : style + } > {virtual ? (
diff --git a/src/components/TreeNode/index.tsx b/src/components/TreeNode/index.tsx index b799de5..65cd253 100644 --- a/src/components/TreeNode/index.tsx +++ b/src/components/TreeNode/index.tsx @@ -42,6 +42,10 @@ export const treeNodePropsPass = { type: Boolean, default: true, }, + showLineNumber: { + type: Boolean, + default: false, + }, // Whether to trigger selection when clicking on the node. selectOnClickNode: { type: Boolean, @@ -227,9 +231,11 @@ export default defineComponent({ showLength, collapsed, showLine, + showLineNumber, editable, editableTrigger, showIcon, + style, } = this; const { @@ -246,10 +252,14 @@ export default defineComponent({ class={{ 'vjs-tree__node': true, 'has-selector': showSelectController, + 'has-carets': showIcon, 'is-highlight': highlightSelectedNode && checked, }} onClick={onNodeClick} + style={style} > + {showLineNumber && {node.id + 1}} + {showSelectController && state.selectable && node.type !== 'objectEnd' && diff --git a/src/components/TreeNode/styles.less b/src/components/TreeNode/styles.less index 95c9629..3d7147d 100644 --- a/src/components/TreeNode/styles.less +++ b/src/components/TreeNode/styles.less @@ -9,8 +9,13 @@ position: relative; line-height: 20px; - &.has-selector { - padding-left: @selector-span; + &.has-carets { + padding-left: 15px; + } + + &.has-selector, + &.has-carets.has-selector { + padding-left: 30px; } &.is-highlight, @@ -32,6 +37,12 @@ } } +.@{css-prefix}-node__index { + position: absolute; + right: 100%; + margin-right: 4px; +} + .@{css-prefix}-comment { color: @comment-color; } diff --git a/src/themes.less b/src/themes.less index 1ed2bfa..e187a67 100644 --- a/src/themes.less +++ b/src/themes.less @@ -21,6 +21,3 @@ /* common border-color */ @border-color: #bfcbd9; - -/* 左侧可选区域占用空间 */ -@selector-span: 30px;