Vue3 代码块高亮显示并可使用富文本编辑器编辑(highlight.js + wangEditor)

发布时间 2023-04-21 14:12:34作者: 闲羊

在Vue项目中实现以下功能:

  功能1. 在页面中显示代码,并将其中的关键字高亮显示。

  功能2. 允许对代码块进行编辑,编辑时代码关键字也高亮显示。

  功能3. 可在编辑器中添加多个代码块,动态渲染代码关键字高亮。

 

Step1: 安装所需插件(本文使用npm安装,若需使用其他方式请查阅官方文档)

安装代码高亮显示插件highlight.js,官方网站:http://highlight.cndoc.wiki

npm install highlight.js

安装highlight.jsvue的集成插件highlightjs/vue-plugin,官方文档:https://github.com/highlightjs/vue-plugin

注意:本文编写时,以下命令会自动安装2.1.0版本,为vue2对应版本,使用vue3需手动将package.json中版本改为2.1.2版本。

npm install @highlightjs/vue-plugin

安装富文本编辑器插件wangEditor,以及对应的vue集成插件,官方网站:https://www.wangeditor.com/

npm install @wangeditor/editor
npm install @wangeditor/editor-for-vue@next

Step2:使用highlight.js实现功能1 -- 在页面中显示代码,并将其中的关键字高亮显示。

<script setup lang="ts">
import { ref } from 'vue';
import 'highlight.js/styles/stackoverflow-light.css'
import 'highlight.js/lib/common';
import hljsVuePlugin from "@highlightjs/vue-plugin";

const code = ref(`let hello = 'Hello World!';
console.log(hello);`)
</script>

<template>
  <hljsVuePlugin.component :code="code" />
</template>

页面效果

Step3:使用wangEditor实现功能2 -- 允许对代码块进行编辑,编辑时代码关键字也高亮显示。

<script setup lang="ts">
import { onBeforeUnmount, ref, shallowRef } from 'vue';
import '@wangeditor/editor/dist/css/style.css';
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';

const editorRef = shallowRef();
const valueHtml = ref(`<pre id="w-e-element-18" data-slate-node="element"><code id="w-e-element-19" data-slate-node="element"><span id="w-e-text-20" data-slate-node="text"><span data-slate-leaf="true"><span data-slate-string="true" class="token keyword">let</span></span><span data-slate-leaf="true"><span data-slate-string="true"> hello </span></span><span data-slate-leaf="true"><span class="token operator" data-slate-string="true">=</span></span><span data-slate-leaf="true"><span data-slate-string="true"> </span></span><span data-slate-leaf="true"><span class="token string" data-slate-string="true">'Hello World!'</span></span><span data-slate-leaf="true"><span class="token punctuation" data-slate-string="true">;</span></span><span data-slate-leaf="true"><span data-slate-string="true">
console</span></span><span data-slate-leaf="true"><span class="token punctuation" data-slate-string="true">.</span></span><span data-slate-leaf="true"><span data-slate-string="true" class="token function">log</span></span><span data-slate-leaf="true"><span class="token punctuation" data-slate-string="true">(</span></span><span data-slate-leaf="true"><span data-slate-string="true">hello</span></span><span data-slate-leaf="true"><span class="token punctuation" data-slate-string="true">)</span></span><span data-slate-leaf="true"><span class="token punctuation" data-slate-string="true">;</span></span></span></code></pre>`);

const toolbarConfig = {
  excludeKeys: []
}
const editorConfig = { placeholder: '请输入内容...' }

// 组件销毁时,也及时销毁编辑器
onBeforeUnmount(() => {
    const editor = editorRef.value
    if (editor == null) return
    editor.destroy()
})

const handleCreated = (editor: any) => {
  editorRef.value = editor // 记录 editor 实例,重要!
}
</script>

<template>
  <div>
    <Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" 
      :defaultConfig="toolbarConfig" mode="default"/>
    <Editor style="height: 500px; overflow-y: hidden;" v-model="valueHtml"
      :defaultConfig="editorConfig" mode="default" @onCreated="handleCreated"/>
  </div>
</template>

页面效果

Step4:使用结合highlight.js和wangEditer实现功能3 -- 可在编辑器中添加多个代码块,动态渲染代码关键字高亮。

<script setup lang="ts">
import { onBeforeUnmount, ref, shallowRef } from 'vue';

import 'highlight.js/styles/stackoverflow-light.css'
import 'highlight.js/lib/common';
import hljs from "highlight.js";

import '@wangeditor/editor/dist/css/style.css';
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';

const editMode = ref(true);

//定义指令,自动使用highlight.js渲染所有<pre><dode>代码块
const vHigelight = {
  mounted(el :any) {
    let blocks = el.querySelectorAll('pre code');
    blocks.forEach((block: HTMLElement)=>{
      block.setAttribute('style', 'margin-top: 8px;');
      hljs.highlightBlock(block)
    })
  }
}

const editorRef = shallowRef();
const valueHtml = ref('');

const toolbarConfig = {
  excludeKeys: []
}
const editorConfig = { placeholder: '请输入内容...' }

// 组件销毁时,也及时销毁编辑器
onBeforeUnmount(() => {
    const editor = editorRef.value
    if (editor == null) return
    editor.destroy()
})

const handleCreated = (editor: any) => {
  editorRef.value = editor // 记录 editor 实例,重要!
}
</script>

<template>
  <div v-if="!editMode">
    <button @click="editMode = true">编辑</button>
    <div v-higelight v-html="valueHtml"></div>
  </div>
  
  <div v-if="editMode">
    <button @click="editMode = false">保存</button>
    <Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" 
      :defaultConfig="toolbarConfig" mode="default"/>
    <Editor style="height: 500px; overflow-y: hidden;" v-model="valueHtml"
      :defaultConfig="editorConfig" mode="default" @onCreated="handleCreated"/>
  </div>
</template>

页面效果

代码Demo地址 https://gitee.com/Yang_Enzhe/Demos/tree/master/RichTextAndCodeHighlight