vue3使用codemirror5循环标记字符串中的内容,并且设置特定的展示样式

<template>
  <div class="sqleditor">
    <textarea ref="codeMirror" class="sqleditor-top"></textarea>
  </div>
</template>
import {
  ref,
  reactive,
  computed,
  watch,
  nextTick,
  defineEmits,
  onMounted,
  onUnmounted,
  markRaw,
  defineExpose
} from "vue";
// 核心样式
import "codemirror/lib/codemirror.css";

// 引入主题后还需要在 options 中指定主题才会生效
import "codemirror/addon/display/fullscreen.css"; // 全屏显示编辑器
import "codemirror/addon/display/fullscreen.js"; // 全屏显示编辑器

import "codemirror/theme/cobalt.css";
import "codemirror/theme/eclipse.css";
import "codemirror/theme/ayu-dark.css";
import "codemirror/theme/idea.css";
import "codemirror/theme/solarized.css";
import "codemirror/addon/hint/show-hint.css";
import "codemirror/addon/hint/show-hint.js";
import "codemirror/addon/hint/sql-hint.js";
import "codemirror/addon/selection/active-line.js";
import "codemirror/addon/edit/matchbrackets.js";
import "codemirror/mode/sql/sql";
import CodeMirror from "codemirror";
//接收父组件传过来的数据
const props = defineProps({
  runLoading: {
    type: Boolean,
    default: false,
  },
  czshow: {
    type: Object,
    default: "",
  },
  dataValue: {
    type: String,
    default: "",
  },
});
//监听数据的变化
watch(
  () => props.dataValue,
  (val) => {
    setValue(val);//设置textarea的值
    markText();//修改需要标记的数据
  }
);
const emit = defineEmits();
const sqlEditor = ref(null);
const codes = ref("");
onMounted(() => {
  init();
  setSize();
  markText();
});
const codeMirror = ref(null);
function init() {
  sqlEditor.value = markRaw(
    CodeMirror.fromTextArea(codeMirror.value, {
      tabSize: 2,
      styleActiveLine: false,
      lineNumbers: true,
      line: false,
      mode: "text/x-sql",
      theme: "solarized",
      lineWrapping: true,
      hintOptions: {
        // 自定义提示选项
        completeSingle: false, // 当匹配只有一项的时候是否自动补全
      },
    })
  );
  setValue(props.dataValue);
  editorEvents();
}
function setValue(sql) {
  sqlEditor.value.setValue(sql);
}
function setSize(width = "500px", height = "300px") {
  sqlEditor.value.setSize(width, height);
}

function editorEvents() {
  // 设置代码提示
  sqlEditor.value.on("keyup", (cm, event) => {
    if (event.keyCode >= 65 && event.keyCode <= 90) {
      cm.showHint();
    }
  });

  // 代码输入的双向绑定
  sqlEditor.value.on("change", (editor) => {
    // 这里要用多一个载体去获取值,不然会重复赋值卡顿
    console.log(editor, "editor");
    codes.value = editor.getValue();
    if (emit) {
      emit("changNameList", codes.value);
    }
  });
}

const marks = ref();
function markText() {
  const param =  sqlEditor.value.getValue()
  // 拆分有特定标识的字符串
  const on = param.match(/\${(.+?)\}/g);
  // 已拆分的字符串去重
  let his = Array.from(new Set(on));
  // 去重之后的数组跟传入的字符串做对比  然后进行标记
  marks.value = [];
  let index = 0;
  sqlEditor.value?.eachLine((line) => {
  his.forEach(i=>{
    let tabIndex = getStrPositions(param,i)
    tabIndex.forEach(item=>{
      let text = document.createElement("span");
      text.className = 'cm-field';
      text.innerText = i;
      const mark = sqlEditor.value?.markText(
        { line: index, ch: item },
        { line: index, ch: item + i.length },
        {
          atomic: true, selectRight: true,
          replacedWith: text,
        }
      );
      mark && marks.value.push(mark);
    })
    
  })
  index++;
});
}
function insertParamToCodeMirror(param) {
  const pos1 = sqlEditor.value.getCursor()
  const pos2 = {}
  pos2.line = pos1.line
  pos2.ch = pos1.ch
  sqlEditor.value.replaceRange(param, pos2)
  markText()
}
// 获取字符串在字符中所有的位置
function getStrPositions(str, subStr) {
  var indexs = [];
  var string = str;
  while (true) {
    var index = string.lastIndexOf(subStr);
    if (index != -1) {
      string =
        string.substr(0, index) + string.substr(index + subStr.length, string.length);
      indexs.push(index);
    } else {
      break;
    }
  }
  return indexs;
}

最终执行效果类似这种

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值