vue实现xml在线编辑功能

news2024/9/22 23:37:01

先看效果 避免误会
在这里插入图片描述
这是一个在线编辑器 我们可以在这上面随意的编写xml代码格式

我们修改上面的内容之后 就可以在控制台输出内容

在这里插入图片描述
如果这正是您想要的东西 那就可以先创建一个vue项目

我们先引入依赖

npm install brace -S
npm install element-ui  -S
npm install vue-clipboard2 -S
npm install vkbeautify --save

然后在src 目录 下新建文件夹 就叫 components
在components下再创建一个文件 叫 editor

然后 在下面创建一个js文件 叫 data_format_utils

data_format_utils.js 参考代码如下


// 对json和xml进行格式化
import vkbeautify from 'vkbeautify'

export function string_to_json_wrap(v) {
  try {
    if (is_json(v)) {
      return unicode_to_china(JSON.stringify(string_to_json(v), null, '\t'))
    } else {
      return v
    }
  } catch (e) {
    console.log(e);
  }
  return v
}

export function json_wrap_to_string(v) {
  try {
    if (is_json(v)) {
      return unicode_to_china(JSON.stringify(string_to_json(v)))

    } else {
      return v
    }

  } catch (e) {
    console.log(e);
  }
  return v
}


export function string_to_xml_wrap(v) {
  try {
    return vkbeautify.xml(v);
  } catch (e) {
    return v
  }
}

export function xml_wrap_to_string(v) {
  try {
    return vkbeautify.xmlmin(v);
  } catch (e) {
    return v
  }
}

export function is_json(str) {
  if (typeof str == 'string') {
    try {
      let obj = JSON.parse(str);
      if (typeof obj == 'object' && obj) {
        return true;
      } else {
        return false;
      }

    } catch (e) {
      return false;
    }
  }
}

export function check_string_type(v) {
  try {
    if (v.startsWith("<!DOCTYPE html")) {
      return 'HTML'
    } else if (v.startsWith("<")) {
      return 'XML'
    } else if (is_json(v)) {
      return 'JSON'
    } else {
      return 'TEXT'
    }
  } catch (e) {
    return 'TEXT'
  }
}

export function wrap_to_string(v, t) {
  let type = t || check_string_type(v)
  switch (type) {
    case 'JSON': {
      return json_wrap_to_string(v)
    }
    case 'XML': {
      return xml_wrap_to_string(v)
    }
    case 'HTML': {
      return xml_wrap_to_string(v)
    }
  }
  return v
}

export function string_to_wrap(v, t) {
  let type = t || check_string_type(v)
  switch (type) {
    case 'JSON': {
      return string_to_json_wrap(v)
    }
    case 'XML': {
      return string_to_xml_wrap(v)
    }
    case 'HTML': {
      return string_to_xml_wrap(v)
    }
  }
  return v
}

export function string_to_json(v) {
  try {
    if (is_json(v)) {
      return v
    } else {
      return v
    }
  } catch (e) {
    return v
  }
}

export function unicode_to_china(input) {
  try {
    return input.replace(/\\\\u([0-9a-fA-F]{2,4})/g, function (string, matched) {
      return String.fromCharCode(parseInt(matched, 16))
    })
  } catch (e) {
    console.log(e);
  }
  return input
}

然后在 editor目录下创建一个组件 我这里叫 index.vue

参考代码如下

<template>
  <div>
    <el-card class="box-card">
      <!-- 操作栏 -->
      <el-row slot="header" class="clearfix" v-if="toolbar == true">
        <el-col :span="5">
          <el-button type="primary" @click="toolsBarLeft">格式化</el-button>
          <el-button type="primary" @click="toolsBarRight">恢复</el-button>
        </el-col>
        <el-col :span="6">
          <el-select v-model="value_type">
            <el-option label="JSON" value="JSON"></el-option>
            <el-option label="TEXT" value="TEXT"></el-option>
            <el-option label="XML" value="XML"></el-option>
            <el-option label="HTML" value="HTML"></el-option>
          </el-select>
        </el-col>
        <el-col :span="2" style="float:right">
          <el-button type="primary" v-clipboard:copy="contentBackup" @click="copy_value">复制</el-button>
        </el-col>
      </el-row>
      <!-- 编辑器 -->
      <div ref="vue_editor" style="height: 50vh;width: 100%"></div>
    </el-card>
  </div>
</template>
<style>
.box-card {
  margin: 20px;
}
.btn-hover {
  padding-left: 6px;
  padding-right: 6px;
}
.btn-hover:hover {
  background: #e0e0e0 !important;
}
.ace-xcode .ace_gutter {
  border-right: none !important;
  background: #fafafa !important;
}
.ace_content_disable {
  background: #fafafa !important;
}
</style>
<script>
// 引入ace代码编辑器
import ace from "brace/index";
import "brace/ext/emmet";
import "brace/ext/language_tools";
import "brace/mode/html";
import "brace/mode/json";
import "brace/mode/text";
import "brace/mode/xml";
import "brace/mode/javascript";
import "brace/theme/xcode";
import "brace/theme/terminal";
import "brace/snippets/javascript";
// 代码格式化方法
import {
  string_to_json_wrap,
  json_wrap_to_string,
  string_to_xml_wrap,
  check_string_type,
  wrap_to_string,
  string_to_wrap
} from "./data_format_utils";
// 主要代码
export default {
  name: "vue_editor",
  /**
   * 参数介绍:
   * value:(必填)双向绑定的数据;
   * theme:(非必填)ace编辑器主题默认xcode,可根据官网自行更换;
   * height:(必填)高度;
   * width:(必填)宽度;
   * options:(非必填)ace编辑器的设置
   * toolbar: (非必填)操作栏;
   * disable:(必填)是否启用编辑功能;
   * type:(非必填)json/xml/html/text,也支持更多,自行引用
   *
   */
  props: {
    value: {
      required: true
    },
    theme: {
      type: String,
      default: "xcode",
      required: false
    },
    options: Object,
    toolbar: {
      required: false,
      default: true,
      type: Boolean
    },
    disable: {
      required: false,
      type: Boolean,
      default: false
    },
    type: {
      required: false,
      type: String
    }
  },
  data() {
    return {
      editor: null,
      contentBackup: "",
      value_type: null,
      internalChange: false
    };
  },
  watch: {
    theme(v) {
      this.editor.setTheme("ace/theme/" + v);
    },
    options(v) {
      this.editor.setOptions(v);
    },
    height() {
      this.$nextTick(function() {
        this.editor.resize();
      });
    },
    width() {
      this.$nextTick(function() {
        this.editor.resize();
      });
    },
    value(v) {
      if (this.editor && !this.internalChange) {
        v = v && v !== null ? v : "";
        typeof v === "object" && (v = JSON.stringify(v));
        this.contentBackup = string_to_wrap(v);
        this.value_type = this.type || check_string_type(this.contentBackup);
        this.editor.session.setValue(this.contentBackup);
      }
    },
    value_type(nv) {
      switch (nv) {
        case "JSON": {
          this.contentBackup = string_to_json_wrap(this.contentBackup);
          this.editor.getSession().setMode("ace/mode/" + nv.toLowerCase());
          this.editor.session.setValue(this.contentBackup);
          break;
        }
        case "TEXT": {
          this.contentBackup = json_wrap_to_string(this.contentBackup);
          this.editor.getSession().setMode("ace/mode/" + nv.toLowerCase());
          this.editor.session.setValue(this.contentBackup);
          break;
        }
        case "XML": {
          this.contentBackup = string_to_xml_wrap(this.contentBackup);
          this.editor.getSession().setMode("ace/mode/" + nv.toLowerCase());
          this.editor.session.setValue(this.contentBackup);
          break;
        }
        case "HTML": {
          this.contentBackup = string_to_xml_wrap(this.contentBackup);
          this.editor.getSession().setMode("ace/mode/" + nv.toLowerCase());
          this.editor.session.setValue(this.contentBackup);
          break;
        }
        // 新增类别
        case "javascript": {
          this.editor.getSession().setMode("ace/mode/" + nv.toLowerCase());
          this.editor.session.setValue(this.contentBackup);
          break;
        }
      }
    },
    disable(v) {
      if (this.editor) {
        this.editor.setReadOnly(v);
        v
          ? this.$refs.vue_editor.classList.add("ace_content_disable")
          : this.$refs.vue_editor.classList.remove("ace_content_disable");
      }
    }
  },
  methods: {
    // 单位校验
    px(n) {
      if (/^\d*$/.test(n)) {
        return n + "px";
      }
      return n;
    },
    // 格式化
    toolsBarLeft() {
      this.contentBackup = string_to_wrap(this.contentBackup, this.value_type);
      this.editor.session.setValue(this.contentBackup);
    },
    // 数据转字符串
    toolsBarRight() {
      this.contentBackup = wrap_to_string(this.contentBackup, this.value_type);
      this.editor.session.setValue(this.contentBackup);
    },
    copy_value() {
      this.$copyText(this.contentBackup).then(
        () => {
          this.$message.success("已经复制到粘贴板!");
        },
        () => {
          this.$message.error("复制失败!");
        }
      );
    },
    onChange() {
      let error = false;
      let v;
      try {
        v = this.editor.getValue();
        error = false;
      } catch (err) {
        error = true;
      }
      if (error) {
        this.$emit("error");
      } else {
        if (this.editor) {
          this.internalChange = true;
          this.contentBackup = v;
          this.$emit("input", v);
          this.$nextTick(() => {
            this.internalChange = false;
          });
        }
      }
    },
    // 编辑器
    initView() {
      this.contentBackup = this.value && this.value !== null ? this.value : "";
      this.value_type = check_string_type(this.value);
      let vm = this;
      let lang = this.lang || "text";
      let theme = this.theme && this.theme !== "xcode" ? this.theme : "xcode";
      let editor_div = this.$refs.vue_editor;
      let editor = (vm.editor = ace.edit(editor_div));
      this.$emit("init", editor);
      editor.$blockScrolling = Infinity;
      editor.setOption("enableEmmet", false);
      editor.getSession().setMode("ace/mode/" + lang);
      editor.setTheme("ace/theme/" + theme);
      editor.getSession().setUseWrapMode(true);
      editor.setShowPrintMargin(false);
      editor.setValue(this.contentBackup);
      editor.on("change", vm.onChange);
      if (vm.options) editor.setOptions(vm.options);
      if (vm.disable) {
        editor.setReadOnly(true);
      }
      // 启用提示
      editor.setOption({
        enableBasicAutocompletion: true,
        enableSnippets: true,
        enableLiveAutocompletion: true
      });
    }
  },
  beforeDestroy() {
    this.editor.destroy();
    this.editor.container.remove();
  },
  mounted() {
    this.initView();
  }
};
</script>

然后在 src下的 main.js全局引入依赖 参考代码如下


import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.config.productionTip = false
Vue.use(ElementUI);

// 引入复制
import VueClipboard from 'vue-clipboard2'
VueClipboard.config.autoSetContainer = true
Vue.use(VueClipboard)

new Vue({
  render: h => h(App),
}).$mount('#app')

然后 因为这是个实验的项目 我就直接将最终引入的代码写在App.vue里啦

在src项目下找到根节点 App.vue组件
参考代码如下

<template>
  <div>
    <!-- 引用插件 -->
    <VueDataEditor
      @input="codeChange"
      :value="code"
      :disable="false"
    ></VueDataEditor>
    <hr />
    <el-button @click="update" type="primary">提交新代码块</el-button>
  </div>
</template>
<script>
import VueDataEditor from "./components/editor";

export default {
  data() {
    return {
      // 双向绑定的值
      code:'<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <build>        <plugins>            <plugin>                <groupId>org.mybatis.generator</groupId>                <artifactId>mybatis-generator-maven-plugin</artifactId>                <version>1.3.2</version>                <configuration>                    <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>                    <verbose>true</verbose>                    <overwrite>true</overwrite>                </configuration>            </plugin>        </plugins>    </build></project>',
      disable: false,
    };
  },
  components: {
    VueDataEditor
  },
  methods: {
    // 子组件传递过来的最新值的方法
    codeChange(event) {
      this.code = event;
    },
    // 打印
    update() {
      console.log(this.code);
    }
  }
};
</script>

启动项目即可实现最开始演示的效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/355832.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

原型链污染

目录 前置知识 原型对象 prototype和__proto__的区别 原型链概念 原型链的继承 原型 链污染 原型链污染原理 javascript中可能会存在原型链污染的危险函数 原型链污染的实际应用 JavaScript中可以触发弹窗的函数 前置知识 原型对象 在JavaScript中&#xff0c;每个函…

9-静态链表及其有关操作

链表可以用malloc/new和结构体加指针的方式来实现&#xff0c;那种实现方式实现的链表又被称为动态链表。但是我们还可以利用数组的方式来实现一个链表&#xff0c;这种实现方式称为静态链表。 静态单链表 我们知道&#xff0c;一个链表节点主要由两大部分组成&#xff1a;数…

黑马Spring学习笔记(一)——IOC/DI核心概念、入门案例

目录 一、Spring系统架构和学习路线 二、Spring核心概念 2.1 IOC、IOC容器、Bean、DI 2.1.1 IOC&#xff08;Inversion of Control&#xff09;控制反转 2.1.2 DI&#xff08;Dependency Injection&#xff09;依赖注入 2.2 核心概念小结 三、入门案例 3.1 IOC入门…

【C++入门】引用、内联函数、auto关键字、基于范围的for循环(C++11)、指针空值nullptr(C++11)

文章目录引用引用概念引用特性引用使用场景常引用内联函数宏的优缺点&#xff1f;C有哪些技术替代宏&#xff1f;auto关键字auto不能推导的场景基于范围的for循环(C11)指针空值nullptr(C11)引用 引用概念 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&…

一篇搞懂UnitTest

unittest单元测试框架是受到 JUnit 的启发&#xff0c;与其他语言中的主流单元测试框架有着相似的风格。其支持测试自动化、支持将测试样例聚合到测试集中&#xff0c;并将测试与报告框架独立开来。unittest模块是Python标准库中的模块。在此之前需要先了解几个概念&#xff1a…

linux高级命令之线程执行带有参数的任务

线程执行带有参数的任务学习目标能够写出线程执行带有参数的任务1. 线程执行带有参数的任务的介绍前面我们使用线程执行的任务是没有参数的&#xff0c;假如我们使用线程执行的任务带有参数&#xff0c;如何给函数传参呢?Thread类执行任务并给任务传参数有两种方式:args 表示以…

NTC热敏电阻

NTC热敏电阻&#xff1a; 负温度系数热敏电阻。 Negative Temperature Coefficient Thermistor 特性&#xff1a; 由锰 (Mn) 、镍 (Ni) 、钴 (Co) 等成分的氧化物烧制而成的陶瓷。阻值随温度上升而下降。 工作温度范围宽&#xff1a;一般的都可用于-40℃ to 125℃。有的高…

[Pytorch] Linear层输出nan

参考链接&#xff1a; https://discuss.pytorch.org/t/well-formed-input-into-a-simple-linear-layer-output-nan/74720/11 总结原因&#xff1a; numpy需要更新 PS. 查看numpy版本号 打开Anaconda Prompt 进入环境 输入命令conda activate envname 然后输入pip show numpy…

MongoDB 自动增长

MongoDB 自动增长 MongoDB 没有像 SQL 一样有自动增长的功能&#xff0c; MongoDB 的 _id 是系统自动生成的12字节唯一标识。但在某些情况下&#xff0c;可能需要实现 ObjectId 自动增长功能。而MongoDB 并没有提供这个功能&#xff0c;那么可以通过编程的方式来实现_id字段自…

Qt音视频开发14-音视频文件保存基类的设计

一、前言 视频综合应用示例&#xff0c;包括了多种内核&#xff0c;在保存文件这个功能上&#xff0c;需要一个通用的文件保存基类AbstractSaveThread&#xff0c;这个基类定义了是否打印线程消息标志位、直接写入还是排队写入标志位、文件生成后是否调用转换合并标志位、是否…

Linux下的Jenkins安装教程

当前环境 CentOS 7.8Java 11&#xff08;注意当前jenkins支持的Java版本最低为Java11&#xff09;FinalShell 3.9&#xff08;操作环境&#xff09; 安装Jenkins PS&#xff1a;不建议使用Docker安装Jenkins&#xff0c;因为使用Jenkins的时候一般会调用外部程序&#xff0c;…

【猜名次】-C语言-题解

1. 描述&#xff1a; 5位运动员参加了10米台跳水比赛&#xff0c;有人让他们预测比赛结果&#xff1a; A选手说&#xff1a;B第二&#xff0c;我第三&#xff1b; B选手说&#xff1a;我第二&#xff0c;E第四&#xff1b; C选手说&#xff1a;我第一&#xff0c;D第二&#x…

【工作10年+的大厂资深架构师万字长文总结 精华收藏!】怎样设计高可用、高性能系统?关于高可用高性能系统架构和设计理论和经验总结...

本文从研发规范层面、应用服务层面、存储层面、产品层面、运维部署层面、异常应急层面这六大层面去剖析一个高可用的系统需要有哪些关键的设计和考虑.O、前言随着业务在线化互联网化的高速发展&#xff0c;企业对核心业务系统的稳定性、可靠性、有效性、业务连续性等有了更高的…

openpnp - 普通航空插头和PCB的连接要使用线对板连接器

文章目录openpnp - 普通航空插头和PCB的连接要使用线对板连接器概述改进实际效果总结ENDopenpnp - 普通航空插头和PCB的连接要使用线对板连接器 概述 和同学讨论问题, 准备将航空插头连接到PCB上. 航空插头选用GX12-4公头, 拧到开孔的铁板上. 然后航空插头公头再与PCB连接. 铁…

【数据库】HNU数据库系统期末考试复习重点

前言 今天刚结束考试&#xff0c;考的范围基本没有超过这套重点内容&#xff0c;觉得整理的这份资料还算比较有用&#xff0c;遂睡前整理了下分享给大家&#xff0c;希望能帮到要准备数据库期末又时间紧张的学弟学妹~ 文章参考&#xff1a; 1.课程老师发《数据库期末考试复习…

【项目精选】基于网络爬虫技术的网络新闻分析(论文+源码+视频)

基于网络爬虫技术的网络新闻分析主要用于网络数据爬取。本系统结构如下&#xff1a; &#xff08;1&#xff09;网络爬虫模块。 &#xff08;2&#xff09;中文分词模块。 &#xff08;3&#xff09;中3文相似度判定模块。 &#xff08;4&#xff09;数据结构化存储模块。 &…

120个IT冷知识,看完就不愁做选择题了

目录 IT冷知识 01-10 1.冰淇淋馅料 2.蠕虫起源 3.Linux和红帽子 4."间谍软件"诞生 5.游戏主机的灵魂 6.Linux之父 7.NetBSD的口号 8.安卓起源 9.不是第七代的 Win 7 10.域名金字塔 11~20 11.神奇魔盒 12. 第一个Ubuntu 正式版本 13.巾帼英雄 14.密码…

【高可用系统架构设计】SLA服务可用性4个9是什么意思?如何保证服务的高可用性 HA(High Availability)?...

如何保证服务的高可用性 HA&#xff08;High Availability&#xff09;?高可用HA&#xff08;High Availability&#xff09;是分布式系统架构设计中必须考虑的因素之一&#xff0c;它通常是指&#xff0c;通过设计减少系统不能提供服务的时间。方法论上&#xff0c;高可用是通…

springboot整合阿里云oss文件服务器

springboot整合阿里云oss文件服务器一、申请Bucket二、 获取AccessKey ID、AccessKey Secret三、 springboot整合3.1 在application.yml 配置参数3.2 oss需要的pom3.3 配置 oss配置类3.4 oss的controller类3.5 oss的service类以及impl一、申请Bucket 进入该网址对象存储oss述 …

18 二叉树

文章目录1 为什么需要树这种数据结构2 树示意图3 二叉树的概念4 二叉树的遍历5 二叉树的遍历的代码实现6 二叉树的遍历查找的代码实现1 为什么需要树这种数据结构 1) 数组存储方式的分析 优点&#xff1a;通过下标方式访问元素&#xff0c;速度快。对于有序数组&#xff0c;还…