Vue接入Monaco Editer代码编辑器

Monaco Editer 代码编辑器

Monaco Editer是微软开发 VScode同款编辑器,功能非常多,几乎可以覆盖页面级代码编辑器的所有使用场景,本文将基于Vite+Vue3封装一个简易的代码编辑器Demo。

在这里插入图片描述

组件代码
<template>
  <div ref="editerWrap" class="code-editer-wrap"></div>
</template>

<script setup>
// 依赖挂载
import monaco from './hooks/dependencies.js';
import { computed, onMounted, ref, watch } from 'vue';

let codeEditer = null;
const editerWrap = ref(null);
const props = defineProps({
  modelValue: {
    type: String,
    default: '',
  },
  config: {
    type: Object,
    default: () => ({
      value: ``,
      fontSize: 14,
      readOnly: false,
      language: 'javascript',
    }),
  },
});
const emits = defineEmits(['change', 'update:modelValue', 'blur', 'focus']);

// 编辑器配置
const codeEditerConfig = computed(() =>
  Object.assign(
    {
      value: props.modelValue,
      fontSize: 14,
      readOnly: false,
      language: 'javascript',
      automaticLayout: true,
      minimap: {
        enabled: true,
      },
      scrollBeyondLastLine: false,
      overviewRulerBorder: false,
    },
    props.config
  )
);

// 初始化编辑器
const initCodeEditer = () => {
  codeEditer = monaco.editor.create(editerWrap.value, codeEditerConfig.value);
};

// 内容变化监听
const initCodeChange = () => {
  codeEditer.onDidChangeModelContent(() => {
    const value = getCodeEditerValue();
    emits('update:modelValue', value);
    emits('change', value);
  });
};

// 焦点变化监听
const blurAndFoucsMoniter = () => {
  codeEditer.onDidBlurEditorText((e) => {
    emits('blur', e);
  });
  codeEditer.onDidFocusEditorText((e) => {
    emits('focus', e);
  });
};

// 获取内容
const getCodeEditerValue = () => codeEditer.getValue();

// 设置内容
const setCodeEditerValue = (val) => codeEditer.setValue(val);

// 格式化代码
const codeEditerFormat = () => codeEditer.trigger('anything', 'editor.action.formatDocument');

// 更新配置
const updateCodeEditerConfig = () => {
  codeEditer.updateOptions(codeEditerConfig.value);
  console.log(codeEditerConfig.value);
};

// 双向绑定,更新编辑器内容
watch(
  () => props.modelValue,
  (val) => {
    if (val !== getCodeEditerValue()) setCodeEditerValue(val);
  }
);

// 监听配置修改
watch(
  () => props.config,
  () => {
    if (codeEditer) updateCodeEditerConfig();
  },
  { immediate: true, deep: true }
);

// 监听语言配置变更
watch(
  () => props.config.language,
  (val) => {
    if (codeEditer) monaco.editor.setModelLanguage(codeEditer.getModel(), val);
  },
  { immediate: true, deep: true }
);

onMounted(() => {
  initCodeEditer();
  initCodeChange();
  blurAndFoucsMoniter();
});

defineExpose({ codeEditerFormat });
</script>

<style lang="less" scoped>
.code-editer-wrap {
  border: 1px solid #ccc;
  height: 100%;
  width: 100%;
}
</style>
代码自动补全Worker挂载 (./hooks/dependencies.js)

目前官方库仅支持以下语言,更多自定义配置可以查看官方文档

import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
import JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker';
import CssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker';
import HtmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker';
import TsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker';

import * as monaco from 'monaco-editor';

self.MonacoEnvironment = {
  getWorker(_, label) {
    if (label === 'json') {
      return new JsonWorker();
    }
    if (label === 'css' || label === 'scss' || label === 'less') {
      return new CssWorker();
    }
    if (label === 'html' || label === 'handlebars' || label === 'razor') {
      return new HtmlWorker();
    }
    if (label === 'typescript' || label === 'javascript') {
      return new TsWorker();
    }
    return new EditorWorker();
  },
};

export default monaco;
引用组件
<script setup>
import CodeEditer from '@/component/CodeEditer/Index.vue';
import { reactive, ref } from 'vue';
const codeEditerValue = ref('');
const codeEditerConfig = reactive({
  fontSize: 14,
  language: 'javascript',
  theme: 'vs-dark',
});
</script>

<template>
  <div class="app-component">
    <div class="center-box">
      <h1>Code Editer Demo</h1>
      <div class="opt-box">
        <el-select v-model="codeEditerConfig.language" class="m-2" placeholder="Select">
          <el-option
            v-for="item in ['python', 'javascript', 'json', 'css', 'html', 'typescript']"
            :key="item"
            :label="item"
            :value="item"
          />
        </el-select>
      </div>
      <div class="edit-area">
        <div class="edit-box">
          <CodeEditer v-model="codeEditerValue" class="code-editer-box" :config="codeEditerConfig"></CodeEditer>
        </div>
        <div class="log-box">
          <el-input
            v-model="codeEditerValue"
            class="textarea"
            :input-style="{ height: '100%' }"
            type="textarea"
            readonly
          ></el-input>
        </div>
      </div>
    </div>
  </div>
</template>

<style lang="less" scoped>
.app-component {
  display: flex;
  justify-content: center;
  align-content: center;

  h1 {
    text-align: center;
  }
  .opt-box {
    margin-bottom: 5px;
  }
  .edit-area {
    display: flex;
    width: 1400px;
    height: 800px;
    .edit-box {
      width: 50%;
      box-sizing: border-box;
      border-radius: 4px;
      overflow: hidden;
    }
    .log-box {
      width: 50%;
      box-sizing: border-box;
      margin-left: 20px;

      .textarea {
        height: 100%;
        font-size: 14px;
      }
    }
  }
}
</style>


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值