You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular实现textarea中JSON实时语法高亮需求及问题

Angular JSON输入实时语法高亮实现方案

核心问题分析

你当前代码的关键问题是:textarea不支持渲染HTML内容,设置innerHTML的操作完全无效,因为textarea仅能处理纯文本。此外你的colorizeJSON函数还存在两个缺陷:

  • 未处理JSON数组的情况
  • 输出的JSON键没有添加双引号,不符合标准JSON格式

方案一:用contenteditable div替代textarea(推荐)

这种方式可以直接渲染HTML高亮内容,同时兼容Angular表单控件:

HTML代码

<div 
  class="json-editor"
  contenteditable="true"
  placeholder="required name and schemaJson object"
  [formControl]="schemaControl"
  (input)="updateHighlight()">
</div>

TypeScript代码

import { Component, OnInit } from '@angular/core';
import { FormControl, Validators } from '@angular/forms';

@Component({
  selector: 'app-json-editor',
  templateUrl: './json-editor.component.html',
  styleUrls: ['./json-editor.component.css']
})
export class JsonEditorComponent implements OnInit {
  schemaControl = new FormControl('', Validators.required);
  originalText = '';

  ngOnInit(): void {
    this.schemaControl.valueChanges.subscribe(value => {
      this.originalText = value || '';
    });
  }

  updateHighlight(): void {
    const editor = document.querySelector('.json-editor') as HTMLElement;
    try {
      const parsed = JSON.parse(this.originalText.trim());
      editor.innerHTML = this.colorizeJSON(parsed);
    } catch (e) {
      editor.innerText = this.originalText;
    }
  }

  colorizeJSON(obj: any): string {
    if (Array.isArray(obj)) {
      let arrayStr = '[';
      obj.forEach((item, index) => {
        arrayStr += this.colorizeJSON(item);
        if (index !== obj.length - 1) arrayStr += ', ';
      });
      return arrayStr + ']';
    }
    if (typeof obj === 'object' && obj !== null) {
      let objStr = '{';
      const keys = Object.keys(obj);
      keys.forEach((key, index) => {
        objStr += `<span class="json-key">"${key}"</span>: `;
        objStr += this.colorizeJSON(obj[key]);
        if (index !== keys.length - 1) objStr += ', ';
      });
      return objStr + '}';
    }
    let valueStr = String(obj);
    if (typeof obj === 'string') {
      valueStr = `"${valueStr}"`;
    }
    return `<span class="json-value">${valueStr}</span>`;
  }
}

CSS代码

.json-editor {
  width: 100%;
  min-height: 200px;
  padding: 10px;
  border: 1px solid #ced4da;
  border-radius: 4px;
  font-family: monospace;
  white-space: pre-wrap;
  word-wrap: break-word;
}

.json-editor[contenteditable]:empty::before {
  content: attr(placeholder);
  color: #999;
}

.json-key {
  color: #268bd2;
  font-weight: bold;
}

.json-value {
  color: #2aa198;
}

方案二:坚持使用textarea(复杂版)

如果必须保留textarea,需要通过隐藏的辅助div计算高亮位置,再通过selectionStart/selectionEnd和动态样式实现,但这种方式需要处理光标位置同步、滚动同步等问题,代码复杂度高,不推荐。


关于Ngx-monaco的补充

如果后续想重新尝试Ngx-monaco,核心注意点:

  1. 确保正确安装依赖:npm install monaco-editor ngx-monaco-editor
  2. 在angular.json中配置monaco的assets路径
  3. 组件中正确初始化编辑器并设置语言为json

内容的提问来源于stack exchange,提问作者Jihed Ben Zarb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 17:52:48