js简单实现一个json格式化功能

8 篇文章 1 订阅
2 篇文章 0 订阅

js简单实现一个json格式化功能

背景

在最近的一个项目中,有个需求是实现json编辑和提交。在我的实现中,使用了在textarea编辑,然后在无序列表中显示json格式化的内容。textarea内编辑json内容会使用“tab”键加入缩进、“shift+tab”减少缩进和格式化json内容的功能,下面主要的内容就是关于这个三个功能。
在线示例

html

<!-- 编辑区域 -->
<textarea
      rows="10"
      cols="30"
      v-on:keydown="tabHandle"
      v-model="content"></textarea>

<!--格式化后的显示区域-->
<ol
    style="height: 60vh;border: 1px solid #ccc;padding-left: 50px;overflow-y: auto"
    >
  <li
      style="list-style: decimal;background: #f8f8f8;"
      v-for="(j, index) in formatJsonList"
      :key="index"
      >
    <pre style="margin:0">{{ j }}</pre>
  </li>
</ol>

核心代码

new Vue({
  el: '#app',
  data: {
    content: '', // 存放编辑的内容
    formatJsonList: [] // 显示json格式化后的内容数组
  },
  watch: {
    // 监听编辑的内容发生改变,这里没有验证json格式是否正确
    content: {
      handler: function(newValue) {
        // 如果值不为空
        if (newValue.length !== 0) {
          this.$set(this, 'formatJsonList', newValue.split('\n'))
          return
        }

        this.$set(this, 'formatJsonList', [])
      },
      deep: true
    },
  },
   methods: {
     // 监听按tab键
     tabHandle(e) {
       if (e.keyCode === 9 || e.which === 9) {
         // shift按键也按下了,就是减少缩进
         if (e.shiftKey) {
           this.shiftTabHandle(e.target)
           e.returnValue = false
           return
         }
         // 只是按了tab,直接插入空格就可以了
         this.insertText(e.target, '  ')
         e.returnValue = false
       }
     },
     // 插入空格
     insertText(el, str) {
       if (document.selection) {
         let sel = document.selection.createRange()
         sel.text = str
       } else if (typeof el.selectionStart === 'number' && typeof el.selectionEnd === 'number') {
         // 选中的开始位置
         let startPos = el.selectionStart
         // 选中的结束位置
         let endPos = el.selectionEnd
         // 鼠标位置
         let cursorPos = startPos
         let tmpStr = el.value
         // 如果当前文本域内容未被选中,加入空格后直接把光标放到后面即可
         if (el.selectionStart === el.selectionEnd) {
           el.value = tmpStr.substring(0, startPos) + str + tmpStr.substring(startPos)
           cursorPos += str.length
           el.selectionStart = el.selectionEnd = cursorPos
           this.moveCursor(el, startPos + str.length)
           return
         }
         // 如果文本域内容被选中了,需要在选中的内容里加入空格
         let selectionStr = tmpStr.substring(startPos, endPos)
         let newStr = ''
         // 把选中的内容添加对应的空格填充
         selectionStr.split('\n').forEach((e, index) => {
           newStr += index === 0 ? '  ' + e : '\n  ' + e
         })
         // 改变为新值
         el.value = tmpStr.substring(0, startPos) + newStr + tmpStr.substring(endPos)
         // 选中当前编辑的内容
         this.selectionContent(el, startPos, startPos + newStr.length)
         return
       } else {
         el.value += str
       }
       this.moveCursor(el, el.value.length)
     },
     // shift和tab同时按下
     shiftTabHandle(el) {
       if (document.selection) {
         let sel = document.selection.createRange()
         sel.text = sel.text.replace(/(\s{0,2}$)/g, '')
       } else if (typeof el.selectionStart === 'number' && typeof el.selectionEnd === 'number') {
         let startPos = el.selectionStart
         let endPos = el.selectionEnd
         let cursorPos = startPos
         let tmpStr = el.value
         // 如果没有选中内容,直接把选中焦点前的内容进行处理,去掉尾空格
         if (el.selectionStart === el.selectionEnd) {
           let reverseStr = tmpStr.substring(0, startPos).replace(/(\s{0,2}$)/g, '')
           cursorPos = reverseStr.length
           el.value = reverseStr + tmpStr.substring(startPos, tmpStr.length)
           el.selectionStart = el.selectionEnd = cursorPos
           this.moveCursor(el, cursorPos)
           return
         }
         // 获取到选中的内容
         let selectionStr = tmpStr.substring(startPos, endPos)
         let newStr = ''
         // 把选中的内容切成数组,并去除数组内的前两个空格
         const selectionStrArray = selectionStr.split('\n')
         selectionStrArray.forEach((e, index) => {
           newStr += index !== 0 ? e.replace(/(^\s{0,2})/, '\n') : e.replace(/(^\s{0,2})/, '')
         })
         // 改变为新值
         el.value = tmpStr.substring(0, startPos) + newStr + tmpStr.substring(endPos)
         // 选中当前编辑的内容
         this.selectionContent(el, startPos, startPos + newStr.length)
         return
       } else {
         el.value = el.value.replace(/(\s{0,2}$)/g, '')
       }
       this.moveCursor(el, el.value.length)
     },
     // 移动光标
     moveCursor(el, toPos) {
       var len = toPos
       if (document.selection) {
         var sel = el.createTextRange()
         sel.moveStart('character', len)
         sel.collapse()
         sel.select()
       } else if (typeof el.selectionStart === 'number' && typeof el.selectionEnd === 'number') {
         el.selectionStart = el.selectionEnd = len
       }
     },
     // 选中内容
     selectionContent(el, start, end) {
       if (el.setSelectionRange) {
         el.setSelectionRange(start, end)
       } else if (el.createTextRange) {
         let rang = el.createTextRange()
         rang.collapse(true)
         rang.moveStart('character', start)
         rang.moveEnd('character', end - start)
         rang.select()
       }
     },
     // 格式化json
     formatJson() {
       let detail = {}
       if (this.content.trim() === '') {
         this.$message.error('当前JSON内容为空!')
         return
       }
       // 验证一下json内容是否正确
       try {
         detail = JSON.parse(this.content)
       } catch (e) {
         console.log(e)
         this.$message({
          showClose: true,
          message: 'JSON格式错误,请检查后再重新尝试格式化',
          type: 'warning'
        })
         return
       }
       // 格式化编辑内容
       this.content = JSON.stringify(detail, null, 2)
     },
   }
})

json内容获取的方法比较简单,就没有在上面写出,可以直接通过“JSON.parse(this.content)”获取到。
代码自测没有问题,如果发现有问题的话,欢迎指正。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值