vue3-ace-editor

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

main.vue

<template>
  <div class="editor-container" :style="{ width: cW, height: cH }">
    <slot></slot>
    <div
      ref="editorEle"
      class="editAceWrap"
      :class="className"
      :style="{ width: cW, height: cH }"
    ></div>
  </div>
</template>
<script setup name="VueAceEditor">
import ace from 'ace-builds';
import { computed, onBeforeUnmount, watch } from "vue";
const { proxy } = getCurrentInstance();
let props = defineProps({
  lang: {
    type: String,
    default: "",
  },
  theme: {
    type: String,
    default: "",
  },
  fontSize: {
    type: Number,
    default: 12,
  },
  content: {
    type: String,
    default: "",
  },
  width: {
    type: [String, Number],
    default: "100%",
  },
  height: {
    type: [String, Number],
    default: "100%",
  },
  className: {
    type: String,
    default: "vue-ace-editor",
  },
  options: {
    type: Object,
    default: () => ({}),
  },
  wrap: {
    type: String,
    default: "free",
  },
  readonly: {
    type: Boolean,
    default: false,
  },
  showPrintMargin: {
    type: Boolean,
    default: false,
  },
});
let editor = ref(null);
let session = ref(null);

const cH = computed(() => {
  if (typeof props.height === "number") return props.height + "px";
  if (typeof props.height === "string") return props.height;
  return "";
});
let cW = computed(() => {
  if (typeof props.width === "number") return props.width + "px";
  if (typeof props.width === "string") return props.width;
  return "";
});
let emits = defineEmits([
  "init",
  "onFocus",
  "update:content",
  "onBlur",
  "onChange",
  "onInput",
  "onCopy",
  "onPaste",
]);
watch(()=>props.fontSize,()=>{
  setFontSize();
})
watch(()=>props.theme,()=>{
  setTheme();
})
watch(()=>props.lang,()=>{
  setMode();
})
watch(()=>props.height,()=>{
  nextTick(() => {
    resize();
  });
})
watch(()=>props.width,()=>{
  nextTick(() => {
    resize();
  });
})
watch(()=>props.content,()=>{
  nextTick(() => {
    setValue();
  });
})
onBeforeUnmount(() => {
  editor.destroy();
  editor.container.remove();
});
onMounted(() => {
  init();
});

function init() {
  editor = ace.edit(proxy.$refs.editorEle);
  editor.$blockScrolling = Infinity;
  session.value = editor.getSession();
  emits("init", editor);
  setMode();
  setTheme();
  setFontSize();
  setOptions();
  setOption();
  setValue();
  setReadonly();
  setShowPrintMargin();
  editor.on("focus", onFocus);
  editor.on("blur", onBlur);
  editor.on("copy", onCopy);
  editor.on("paste", onPaste);
  editor.on("change", onChange);
  editor.on("input", onInput);
}
function setMode() {
  session.value.setMode(`ace/mode/${props.lang}`);
  session.value.setUseWrapMode(true);
  return editor;
}
function setTheme() {
  editor.setTheme(`ace/theme/${props.theme}`);
  return editor;
}
function setFontSize() {
  editor.setFontSize(props.fontSize);
  return editor;
}
function setValue() {
  session.value.setValue(props.content);
  return editor;
}
function getValue() {
  return editor.getValue();
}
function setOptions() {
  editor.setOptions(props.options);
  return editor;
}
function setOption() {
  editor.setOption("wrap", props.wrap);
  return editor;
}
function setReadonly() {
  editor.setReadOnly(props.readonly);
  return editor;
}
function setShowPrintMargin() {
  editor.setShowPrintMargin(props.showPrintMargin);
  return editor;
}
function setCompleteData(data) {
  ace.acequire("ace/ext/language_tools").addCompleter({
    getCompletions(editor, session, pos, prefix, callback) {
      return callback(null, data);
    },
  });
}
function setAutocomplete() {
  editor.execCommand("startAutocomplete");
  return editor;
}
function getRowCol() {
  return editor.selection.getCursor();
}
function onFocus() {
  emits("onFocus", editor);
}
function onBlur() {
  emits("update:content", getValue());
  emits("onBlur", editor);
}
function onChange() {
  emits("onChange", editor);
}
function onInput() {
  emits("onInput", editor);
}
function onCopy() {
  emits("onCopy", editor);
}
function onPaste() {
  emits("onPaste", editor);
}

function resize() {
  editor.resize();
  return editor;
}
function setRange(startRow, startCol, endRow, endCol) {
  const Range = ace.acequire("ace/range").Range;
  return new Range(startRow, startCol, endRow, endCol);
}
function getTextRange(r) {
  return session.value.getTextRange(r);
}
function save(storageName) {
  localStorage[storageName] = getValue();
  session.value.getUndoManager().markClean();
  return editor;
}
function undo() {
  editor.undo();
  return editor;
}
function redo() {
  editor.redo();
  return editor;
}
defineExpose({
  session,
  setValue,
  getValue
})
</script>
<style scoped>
.editor-container {
  position: relative;
}
.editAceWrap{
  /* touch-action: none; */
}
:deep(.ace_scrollbar-inner){
  background-color: #272822;
}
:deep(.ace_scrollbar-v){
  background-color: #fff;
}
</style>

ace.config.js

https://blog.csdn.net/youhebuke225/article/details/129216377

full-screen-ace-editor.vue

<template>
  <el-row style="width: 100%">
    <el-dialog
      ref="dialog"
      append-to-body
      :close-on-click-modal="false"
      draggable
      width="900px"
      :title="title"
      v-model="isFullscreen"
      top="8vh"
    >
      <vue-ace-editor
        ref="aceEditor1"
        v-bind="$attrs"
        :content="innerValue"
        :height="dialogBodyHeight"
        :readonly="disabled"
        @onBlur="aceEditorInput"
      />
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary" @click="isFullscreen = false"
            >关 闭</el-button
          >
        </span>
      </template>
    </el-dialog>
    <el-col class="flex-sub">
      <vue-ace-editor
        ref="aceEditor2"
        v-bind="$attrs"
        :content="innerValue"
        :readonly="disabled"
        @onBlur="aceEditorInput"
      />
    </el-col>
    <el-col v-if="!noFullScreen" class="text-right full-screen-btn">
      <el-button
        icon="FullScreen"
        type="text"
        class="padding-0 large"
        title="在新窗口显示"
        @click="isFullscreen = true"
      />
    </el-col>
  </el-row>
</template>

<script setup name="FullScreenAceEditor">
import "./ace.config.js";
const { proxy } = getCurrentInstance();
let props = defineProps({
  title: {
    type: String,
    default: "",
  },
  content: {
    type: String,
    default: "",
  },
  noFullScreen: {
    type: Boolean,
    default: false,
  },
  disabled: {
    type: Boolean,
    default: false,
  },
});
let isFullscreen = ref(false);
let innerValue = ref("");
let dialogBodyHeight = ref(0);
let emits = defineEmits(["update:content"]);
let inputValue = ref("");
watch(
  () => props.content,
  (newValue) => {
    nextTick(() => {
      inputValue.value = newValue;
      proxy.$refs.aceEditor2.session.setValue(newValue);
    });
  },
  { immediate: true }
);
watch(inputValue, (val) => {
  emits("update:content", val);
});
watch(isFullscreen, (val) => {
  if (val) {
    nextTick(() => {
      // const { height } = proxy.$refs.dialog.$el.getBoundingClientRect();
      // if (height) {
      //   dialogBodyHeight.value = height - 80;
      // }
      dialogBodyHeight.value = 600;
      proxy.$refs.aceEditor1.session.setValue(inputValue.value);
    });
  }
});

function aceEditorInput(editor) {
  emits("update:content", editor.getValue());
}
function resize() {
  proxy.$refs?.aceEditor1?.resize?.();
  proxy.$refs?.aceEditor2?.resize?.();
}
</script>

<style lang="scss" scoped>
.full-screen-btn {
  width: 30px;
  position: absolute;
  right: 10px;
  top: -2px;
  z-index: 2000;
}
</style>

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值