VueJS/NUXTJS项目中如何在textarea内高亮XML/JSON语法错误对应行
解决方案
你要实现的效果可以分两步完成:先获取语法错误的行号,再实现textarea区域的错误行高亮,以下是可直接落地的实现方案:
第一步:获取XML/JSON语法错误的行号
JSON错误行号获取
原生JSON.parse无法返回行位置,你可以替换为jsonlint-mod库,校验错误时会直接返回错误行、列信息:
- 安装依赖:
npm i jsonlint-mod - 替换原有校验逻辑:
import jsonlint from 'jsonlint-mod' try { jsonlint.parse(inputJSON) // 校验通过后的业务逻辑 } catch (e) { const errLine = e.line // 错误行号 const errCol = e.column // 错误列号 const message = `Provided JSON is syntactically incorrect. Error at line ${errLine}: ${e.message}` console.log(message) }
XML错误行号获取
你在用的fast-xml-parser本身就支持返回错误位置,只要开启includeLocations配置即可:
import { XMLValidator } from 'fast-xml-parser' const validationResult = XMLValidator.validate(inputXML, { includeLocations: true // 开启位置信息返回 }) if (validationResult !== true) { const errLine = validationResult.err.lineNumber // 错误行号 const errCol = validationResult.err.colNumber // 错误列号 const message = `Provided XML is syntactically incorrect. Error at line ${errLine}: ${validationResult.err.msg}` console.log(message) return }
第二步:实现textarea错误行高亮
原生textarea不支持局部内容样式自定义,有两种成熟方案可以选:
方案1:轻量自定义封装(无额外编辑器依赖)
原理是在透明的原生textarea下方叠加一个等高的背景容器,渲染每行内容和错误高亮样式,和你原有输入逻辑完全兼容,Vue/Nuxt下的示例代码如下:
<template> <div class="code-editor-wrap"> <!-- 背景层:渲染行号和错误高亮 --> <div class="code-bg" aria-hidden="true"> <div v-for="(line, idx) in contentLines" :key="idx" class="code-line" :class="{ 'error-line': idx + 1 === currentErrorLine }" > <span class="line-num">{{ idx + 1 }}</span> <span class="line-content">{{ line }}</span> </div> </div> <!-- 原生输入层:透明覆盖在背景上方 --> <textarea v-model="inputContent" class="code-textarea" @input="clearError" rows="15" ></textarea> </div> </template> <script setup> import { ref, computed } from 'vue' const inputContent = ref('') const currentErrorLine = ref(0) // 校验完成后把错误行号赋值给这个变量即可触发高亮 const contentLines = computed(() => inputContent.value.split('\n')) const clearError = () => currentErrorLine.value = 0 </script> <style scoped> .code-editor-wrap { position: relative; border: 1px solid #eee; border-radius: 4px; font-family: monospace; font-size: 14px; } .code-bg { position: absolute; top: 0; left: 0; width: 100%; height: 100%; padding: 8px 0; background: #fff; } .code-line { display: flex; padding: 0 8px; line-height: 22px; } .line-num { width: 40px; color: #999; text-align: right; padding-right: 12px; user-select: none; } .error-line { background: #fee2e2; /* 错误行高亮颜色,可自定义 */ } .code-textarea { position: relative; z-index: 1; width: 100%; padding: 8px 8px 8px 60px; border: none; outline: none; background: transparent; color: transparent; caret-color: #000; font-family: inherit; font-size: inherit; line-height: 22px; resize: vertical; } </style>
方案2:使用成熟代码编辑器组件(开发效率更高)
如果不需要严格限制依赖,直接用封装好的代码编辑器组件即可,自带语法校验、错误高亮、行号显示能力,不需要自己写校验和渲染逻辑:
- Vue3/Nuxt3场景推荐用
vue-codemirror,搭配@codemirror/lang-json、@codemirror/lang-xml语言包,开启语法校验配置后会自动标记错误行 - 也可以用VSCode同款的
monaco-editor的Vue封装版本,内置JSON/XML语法校验能力,开启配置后自动返回错误位置并高亮
内容的提问来源于stack exchange,提问作者BATMAN_2008
相关产品推荐
相关产品推荐

