前两天干活儿有个需求,在前端需要展示可折叠的Json树,供开发人员查看,这里采用JsonView组件来实现,它是一款用于展示Json的Vue组件,支持大体积的Json文件快速解析渲染,下面记录一下实现过程。
1.首先先下载好JsonView的组件:JsonView.vue,组件代码如下:
1 <template> 2 <div class="bgView"> 3 <div :class="['json-view', length ? 'closeable' : '']" :style="'font-size:' + fontSize+'px'"> 4 <span @click="toggleClose" :class="['angle', innerclosed ? 'closed' : '']" v-if="length"> 5 </span> 6 <div class="content-wrap"> 7 <p class="first-line"> 8 <span v-if="jsonKey" class="json-key">"{{jsonKey}}": </span> 9 <span v-if="length"> 10 {{prefix}} 11 {{innerclosed ? ('...' + subfix) : ''}} 12 <span class="json-note"> 13 {{innerclosed ? (' // count: ' + length) : ''}} 14 </span> 15 </span> 16 <span v-if="!length">{{isArray ? '[]' : '{}'}}</span> 17 </p> 18 <div v-if="!innerclosed && length" class="json-body"> 19 <template v-for="(item, index) in items"> 20 <json-view :closed="closed" v-if="item.isJSON" :key="index" :json="item.value" 21 :jsonKey="item.key" :isLast="index === items.length - 1"></json-view> 22 <p class="json-item" v-else :key="index"> 23 <span class="json-key"> 24 {{(isArray ? '' : '"' + item.key + '"')}} 25 </span> 26 : 27 <span class="json-value"> 28 {{item.value + (index === items.length - 1 ? '' : ',')}} 29 </span> 30 </p> 31 </template> 32 <span v-show="!innerclosed" class="body-line"></span> 33 </div> 34 <p v-if="!innerclosed && length" class="last-line"> 35 <span>{{subfix}}</span> 36 </p> 37 </div> 38 </div> 39 </div> 40 </template> 41 42 <script> 43 export default { 44 name: 'jsonView', 45 props: { 46 json: [Object, Array], 47 jsonKey: { 48 type: String, 49 default: '' 50 }, 51 closed: { 52 type: Boolean, 53 default: false 54 }, 55 isLast: { 56 type: Boolean, 57 default: true 58 }, 59 fontSize: { 60 type: Number, 61 default: 13 62 } 63 }, 64 created() { 65 this.innerclosed = this.closed 66 this.$watch('closed', () => { 67 this.innerclosed = this.closed 68 }) 69 }, 70 data() { 71 return { 72 innerclosed: true 73 } 74 }, 75 methods: { 76 isObjectOrArray(source) { 77 const type = Object.prototype.toString.call(source) 78 const res = type === '[object Array]' || type === '[object Object]' 79 return res 80 }, 81 toggleClose() { 82 if (this.innerclosed) { 83 this.innerclosed = false 84 } else { 85 this.innerclosed = true 86 } 87 } 88 }, 89 computed: { 90 isArray() { 91 return Object.prototype.toString.call(this.json) === '[object Array]' 92 }, 93 length() { 94 return this.isArray ? this.json.length : Object.keys(this.json).length 95 }, 96 subfix() { 97 return (this.isArray ? ']' : '}') + (this.isLast ? '' : ',') 98 }, 99 prefix() { 100 return this.isArray ? '[' : '{' 101 }, 102 items() { 103 if (this.isArray) { 104 return this.json.map(item => { 105 const isJSON = this.isObjectOrArray(item) 106 return { 107 value: isJSON ? item : JSON.stringify(item), 108 isJSON, 109 key: '' 110 } 111 }) 112 } 113 const json = this.json 114 return Object.keys(json).map(key => { 115 const item = json[key] 116 const isJSON = this.isObjectOrArray(item) 117 return { 118 value: isJSON ? item : JSON.stringify(item), 119 isJSON, 120 key 121 } 122 }) 123 } 124 } 125 } 126 </script> 127 128 <style> 129 .bgView { 130 background-color: #fafafa; 131 } 132 133 .json-view { 134 position: relative; 135 display: block; 136 100%; 137 height: 100%; 138 white-space: nowrap; 139 padding-left: 20px; 140 box-sizing: border-box; 141 } 142 143 .json-note { 144 color: #909399; 145 } 146 147 .json-key { 148 color: rgb(147, 98, 15); 149 } 150 151 .json-value { 152 color: rgb(24, 186, 24); 153 } 154 155 .json-item { 156 margin: 0; 157 padding-left: 20px; 158 } 159 160 .first-line { 161 padding: 0; 162 margin: 0; 163 } 164 165 .json-body { 166 position: relative; 167 padding: 0; 168 margin: 0; 169 } 170 171 .json-body .body-line { 172 position: absolute; 173 height: 100%; 174 0; 175 border-left: dashed 1px #bbb; 176 top: 0; 177 left: 2px; 178 } 179 180 .last-line { 181 padding: 0; 182 margin: 0; 183 } 184 185 .angle { 186 position: absolute; 187 display: block; 188 cursor: pointer; 189 float: left; 190 20px; 191 text-align: center; 192 left: 0; 193 } 194 195 .angle::after { 196 content: ""; 197 display: inline-block; 198 0; 199 height: 0; 200 vertical-align: middle; 201 border-top: solid 4px #333; 202 border-left: solid 6px transparent; 203 border-right: solid 6px transparent; 204 } 205 206 .angle.closed::after { 207 border-left: solid 4px #333; 208 border-top: solid 6px transparent; 209 border-bottom: solid 6px transparent; 210 } 211 </style>
2.在需要使用的vue页面中引用JsonView组件
import JsonView from '@/components/JsonView'
3.定义Json数据变量
jsonData:{},
4.页面展示代码
<JsonView :json="jsonData"></JsonView>
5.实现效果如下:
JsonView Attributes
打完收工!