vue3脚本绑定CodeMirror的使用

 代码:

<template>
  <CodeMirror
    ref="codeMirror"
    :value="codeVal"
    :languageSingle="languageSingle"
    :readOnly="!isEdit"
    @submitCode="submitCode"
  >
  </CodeMirror>
</template>

<script setup>
import { getFuncInfo, editFuncInfo } from "@/api/algorithm.js";
import CodeMirror from "@/components/CodeMirror/index.vue";
import { message } from "ant-design-vue";
import { ref, onMounted } from "vue";
const formData = ref({});
const props = defineProps({
  id: { type: String },
  isEdit: { type: Boolean, default: false },
});
const codeVal = ref("");
const formdata = ref({});
const languageSingle = ref({});
function dealData(res) {
  if (JSON.stringify(res) !== "{}") {
    if (res.algorithmBody !== null) {
      const algorithmBody = JSON.parse(res.algorithmBody);
      codeVal.value = algorithmBody.content;
      languageSingle.value = {
        val: algorithmBody.typeMode,
        label: algorithmBody.type,
      };
    }
  } else {
    console.log("ccc");
    languageSingle.value = {};
  }
}
function submitCode(type, typeMode, content) {
  const params = {
    type: type,
    typeMode: typeMode,
    content: content,
  };
  editFuncInfo({ id: formData.value.id, algorithmBody: JSON.stringify(params) })
    .then((res) => {
      if (JSON.stringify(res) !== "") {
        message.success("保存成功");
        dealData(res);
      } else {
        message.error("保存失败");
      }
    })
    .catch((err) => {
      message.error("保存失败");
    });
}
onMounted(() => {
  console.log("基本信息");
  getData();
});
const dataOld = ref();
const getData = () => {
  getFuncInfo({ id: props.id }).then((res) => {
    formData.value.groupName = res.algorithmGroup.name;
    formData.value = { ...formData.value, ...res };
    dataOld.value = { ...formData.value, ...res };
    dealData(res);
  });
};
</script>
<style lang="less" scoped>
.json_box {
  padding: 20px 15px;
  border: 1px solid #e8e8e8;
  min-height: calc(100vh - 280px);
}
:deep(.jv-container .jv-code) {
  padding: 0 !important;
}
</style>

codeMirror组件

<template>
  <div class="in-coder-panel">
    <div class="select-box">
      选择语言:
      <a-select
        class="code-mode-select"
        @change="changeMode"
        v-model:value="language"
        :disabled="single || readOnly"
      >
        <a-select-option v-for="i in modes" :key="i.value" :value="i.value">
          {
   
   { i.label }}
        </a-select-option>
      </a-select>
      <span class="run_btn" v-show="!readOnly">
        <!-- <a-icon type="play-circle" theme="filled" title="运行" /> -->
        <span class="saveBtn" @click="saveCode">保存</span>
      </span>
      <!-- <a-icon class="run_btn" type="play-circle" theme="filled" title="运行" v-if="!readOnly"/> -->
    </div>
    <textarea ref="textarea"></textarea>
  </div>
</template>

<script setup>
import { ref, onMounted, watch } from "vue";
// 引入全局实例
import _CodeMirror from "codemirror";
// import { Codemirror } from "vue-codemirror";
//   // 核心样式
import "codemirror/lib/codemirror.css";
// 引入主题后还需要在 options 中指定主题才会生效
import "codemirror/theme/eclipse.css";
// import 'codemirror/addon/hint/show-hint.css'
// import 'codemirror/addon/hint/show-hint.js'
// 折叠
import "codemirror/addon/fold/foldgutter.css";
import "codemirror/addon/fold/foldcode";
import "codemirror/addon/fold/foldgutter";
import "codemirror/addon/fold/brace-fold";
import "codemirror/addon/fold/comment-fold";
// 需要引入具体的语法高亮库才会有对应的语法高亮效果
// codemirror 官方其实支持通过 /addon/mode/loadmode.js 和 /mode/meta.js 来实现动态加载对应语法高亮库
// 但 vue 貌似没有无法在实例初始化后再动态加载对应 JS ,所以此处才把对应的 JS 提前引入
import "codemirror/mode/javascript/javascript.js";
import "codemirror/mode/css/css.js";
import "codemirror/mode/xml/xml.js";
import "codemirror/mode/clike/clike.js";
import "codemirror/mode/markdown/markdown.js";
import "codemirror/mode/python/python.js";
import "codemirror/mode/r/r.js";
import "codemirror/mode/shell/shell.js";
import "codemirror/mode/sql/sql.js";
import "codemirror/mode/swift/swift.js";
import "codemirror/mode/vue/vue.js";
import { message } from "ant-design-vue";
const props = defineProps({
  value: {
    type: String,
    default: "",
  },
  languageSingle: {
    type: Object,
    default: () => {
      return {};
    }, // text/**//x-sql
  },
  readOnly: {
    type: Boolean,
    default: false,
  },
  single: {
    type: Boolean,
    default: false,
  },
});
// 尝试获取全局实例
const CodeMirror = ref(window.CodeMirror || _CodeMirror);
const code = ref();
const mode = ref("javascript");
let coder = null;
const languageType = ref("");
const language = ref("");
const options = ref({
  // 缩进格式
  tabSize: 4,
  // 主题,对应主题库 JS 需要提前引入
  theme: "eclipse",
  // 显示行号
  lineNumbers: true,
  line: true,
  foldGutter: true,
  lineWrapping: true,
  gutters: [
    "CodeMirror-linenumbers",
    "CodeMirror-foldgutter",
    "CodeMirror-lint-markers",
  ],
  matchTags: { bothTags: true },
  extraKeys: { Ctrl: "autocomplete" },
});
const modes = ref([
  // {
  //   value: 'css',
  //   label: 'CSS'
  // }, {
  //   value: 'javascript',
  //   label: 'Javascript'
  // }, {
  //   value: 'html',
  //   label: 'XML/HTML'
  // }, {
  //   value: 'x-java',
  //   label: 'Java'
  // }, {
  //   value: 'x-csrc',
  //   label: 'C'
  // }, {
  //   value: 'x-c++src',
  //   label: 'C++'
  // },
  {
    value: "x-csharp",
    label: "C#",
  },
  {
    value: "x-sql",
    label: "SQL",
  },
  {
    value: "javascript",
    label: "Javascript",
  },
  //  {
  //   value: 'x-python',
  //   label: 'Python'
  // }, {
  //   value: 'x-rsrc',
  //   label: 'R'
  // }, {
  //   value: 'x-sh',
  //   label: 'Shell'
  // }, {
  //   value: 'x-sql',
  //   label: 'SQL'
  // }, {
  //   value: 'x-swift',
  //   label: 'Swift'
  // }, {
  //   value: 'x-vue',
  //   label: 'Vue'
  // }, {
  //   value: 'markdown',
  //   label: 'Markdown'
  // }
]);
onMounted(() => {
  _initialize();
  //
});
defineExpose({
  _initialize,
  CodeMirror,
  coder,
  language,
});
const textarea = ref();
// 初始化
function _initialize() {
  CodeMirror.value = window.CodeMirror || _CodeMirror;
  // 初始化编辑器实例,传入需要被实例化的文本域对象和默认配置
  coder = CodeMirror.value.fromTextArea(textarea.value, options.value);
  // 编辑器赋值
  if (props.value || code.value) {
    coder.setValue(props.value || code.value);
  } else {
    coder.setValue("");
  }
  code.value = props.value;
  // 支持双向绑定
  coder.on("change", (coder) => {
    code.value = coder.getValue();
    // if (this.$emit) {
    //   this.$emit('input', this.code)
    // }
  });
  // 尝试从父容器获取语法类型
  if (JSON.stringify(props.languageSingle) !== "{}") {
    if (props.languageSingle.val) {
      language.value = props.languageSingle.val;
    }
    //  language.value = props.languageSingle.val? props.languageSingle.val:''
    languageType.value = props.languageSingle.label;
    coder.setOption("mode", `text/` + language.value);
  }
  coder.setOption("readOnly", props.readOnly);
}
// 获取当前语法类型
function _getLanguage(language) {
  // 在支持的语法类型列表中寻找传入的语法类型
  return modes.value.find((mode) => {
    // 所有的值都忽略大小写,方便比较
    const currentLanguage = language.toLowerCase();
    const currentLabel = mode.label.toLowerCase();
    const currentValue = mode.value.toLowerCase();

    // 由于真实值可能不规范,例如 java 的真实值是 x-java ,所以讲 value 和 label 同时和传入语法进行比较
    return currentLabel === currentLanguage || currentValue === currentLanguage;
  });
}
const emits = defineEmits(["submitCode", "language-change"]);
// 更改模式
function changeMode(val) {
  language.value = val;
  // 修改编辑器的语法配置
  coder.setOption("mode", `text/${val}`);
  // 获取修改后的语法
  const label = _getLanguage(val).label.toLowerCase();
  // 允许父容器通过以下函数监听当前的语法值
  // emits('language-change',label)
  languageType.value = label;
}
function saveCode() {
  if (!languageType.value) {
    message.warning("请选择语言!");
    return;
  }
  if (!code.value) {
    message.warning("请输入函数!");
    return;
  }
  emits("submitCode", languageType.value, language.value, code.value);
}
watch(
  () => props.readOnly,
  (val, oldVal) => {
    coder.setOption("readOnly", val);
  }
  // { deep: true, immediate: true }
);
watch(
  () => props.value,
  (newVal, oldVal) => {
    console.log("fff");
    if (newVal) {
      console.log("nrr", newVal);
      props.value = newVal;
      CodeMirror.value = null;
      if (props.value || code.value) {
        coder.setValue(props.value || code.value);
      }
      code.value = props.value;
      if (JSON.stringify(props.languageSingle) !== "{}") {
        if (props.languageSingle.val) {
          language.value = props.languageSingle.val;
        }
        //  language.value = props.languageSingle.val? props.languageSingle.val:''
        languageType.value = props.languageSingle.label;
        coder.setOption("mode", `text/` + language.value);
      }
      // _initialize ()
    } else {
      console.log("实现");
      //    if(CodeMirror.value){
      //              coder.value.setValue('')
      //    CodeMirror.value=null
      //    coder.value=null
      // code.value=''
      // languageType.value=''
      //    }
    }
  },
  { deep: true, immediate: true }
);
</script>
<style lang="less" scoped>
.in-coder-panel {
  position: relative;
  height: 660px;
  :deep(.CodeMirror) {
    flex-grow: 1;
    z-index: 1;
    height: calc(100% - 52px);
    border-top: 1px solid #dddddd;
    .CodeMirror-code {
      line-height: 19px;
    }
  }
  .CodeMirror-sizer {
    padding-top: 10px;
  }
  .select-box {
    padding-left: 15px;
    .code-mode-select {
      width: 200px;
      margin: 10px 0 10px;
    }
  }
  .run_btn {
    float: right;
    margin: 15px 20px 0;
    font-size: 24px;
    cursor: pointer;
    i {
      margin-left: 10px;
      &:hover {
        color: #357ad4;
      }
    }
  }
  .saveBtn {
    font-size: 16px;
    padding: 3px 20px;
    border-radius: 2px;
    background-color: #2d77e8;
    color: #fff;
    position: absolute;
    right: 20px;
    top: 18px;
  }
}
.in-coder-panel {
  :deep(.CodeMirror):nth-child(1) {
    display: none !important;
  }
}
</style>

猜你喜欢

转载自blog.csdn.net/qq_46617584/article/details/131600404