Skip to content

代码编辑器

作者:Yuan Tang
更新于:5 个月前
字数统计:648 字
阅读时长:2 分钟

在页面中想要效仿 MDN 网站 CSS 模块的效果,用户输入后右侧效果动态修改,渲染最新的效果。

组件封装

询问 ChatGPT,得到的回复是可以使用 NPM 下载的第三方组件 CodeMirror 。由于没有具体的官方文档介绍 Vue 项目如何使用,下面是询问 GPT 后得到的步骤:

  1. 下载相关依赖

    txt
    pnpm i codemirror
    pnpm i vue-codemirror
    pnpm i @codemirror/lang-css
    pnpm i @codemirror/lang-javascript
    pnpm i @codemirror/theme-one-dark

    前两个依赖主要是下载第三方组件和 Vue 适配的组件;中间两个是该组件语法高亮的语言;最后一个是皮肤,暗黑模式。

  2. 新建一个子组件,导入依赖并声明使用组件

    vue
    <script setup>
    import { Codemirror } from 'vue-codemirror'
    
    const emit = defineEmits(['change'])
    
    const code = defineModel()
    
    function handleChange(e) {
      emit('change', e)
    }
    </script>
    
    <template>
      <Codemirror
        v-model="code"
        placeholder="暂无数据..."
        :autofocus="false"
        :tab-size="2"
        @change="handleChange"
      />
    </template>

    其中,tabSize 为每行前面缩进几个字符,autofocus 表示是否自动聚焦,code 是父传子双向绑定的数据,修改内容会触发 change 事件。

  3. 设置编辑器的语言和皮肤模式

    通过父子传参的形式,动态设置编辑器的高亮语言语法,再和皮肤作为一个数组传递给组件的 extensions 变量。最后设置一下样式即可。

    vue
    <script setup>
    import { Codemirror } from 'vue-codemirror'
    
    import { javascript } from '@codemirror/lang-javascript'
    
    import { css } from '@codemirror/lang-css'
    
    import { vue } from '@codemirror/lang-vue'
    
    import { oneDark } from '@codemirror/theme-one-dark'
    
    import { screenWidth } from '@/store/index.js'
    
    
    const props = defineProps({ 
      language: { 
        type: String, 
        default: 'css'
      }, 
      disabled: { 
        type: [String, Boolean], 
        default: false
      }, 
      style: { 
        type: [Object], 
        default: () => ({}) 
      } 
    }) 
    const emit = defineEmits(['change'])
    
    const { language, disabled, style } = toRefs(props) 
    
    const lang = ref(null) 
    const extensions = ref(null) 
    watch(() => language.value, (newVal) => { 
      lang.value = { javascript, css, vue }[language.value] 
      extensions.value = [lang.value(), oneDark] 
    }, { immediate: true }) 
    const code = defineModel()
    const comStyle = computed(() => ({ ...style.value, ...{ height: screenWidth.value > 768 ? '300px' : '18.75rem' } })) 
    
    function handleChange(e) {
      emit('change', e)
    }
    </script>
    
    <template>
      <Codemirror
        v-model="code"
        :disabled="disabled"
        placeholder="暂无数据..."
        :style="comStyle"
        :autofocus="false"
        :indent-with-tab="true"
        :tab-size="2"
        :full-screen="true"
        :extensions="extensions"
        @change="handleChange"
      />
    </template>

组件使用

现在封装好了一个 code 组件可以使用了,父组件只需要 v-model 双向绑定代码文本,通过 language 指定代码语言风格即可。示例代码如下:

vue
<script setup>
import Code from './code.vue'

const code = ref('clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)')
</script>

<template>
  <Code
    v-model="code"
    class="code"
    language="css"
  />
</template>

再搭配一个 DOM 节点,可用于查看设置的样式。效果如下所示:

样式修改

Contributors

Yuan Tang