• vue3项目中使用富文本编辑器


    前言

    适配 Vue3 的富文本插件不多,我看了很多插件官网,也有很多写的非常棒的,有UI非常优雅让人耳目一新的,也有功能非常全面的。
    如:

    1. Quill,简单易用,功能全面。
    2. editorjs,UI极其优雅,非常好看。
    3. ckeditor-5,一款完全重写的富文本编辑器,支持现代 Web 标准,例如模块化架构、原生语义化输出等。

    还有很多优秀的富文本编辑器插件,就不一一列举了。

    可惜这些都只有英文原文档,对于我这样英语阅读能力不是很好的人来说,实在是一种煎熬,当然也是因为周期比较短,没有时间去研究,所以选择了这一款易上手的插件 wangEditor

    推荐原因有二:

    1. wangEditor 有详细的中文文档,以及中文交流环境。因为作者就是国内程序员。
    2. wangEditor 基于 slate 内核开发,但不依赖于 React ,所以它本身无框架依赖。

    一、安装

    安装 wangeditor 插件

    npm install @wangeditor/editor --save
    # yarn add @wangeditor/editor
    
    • 1
    • 2

    安装 Vue3 组件

    npm install @wangeditor/editor-for-vue@next --save
    # yarn add @wangeditor/editor-for-vue@next
    
    • 1
    • 2

    二、使用

    1. 简单使用

    这个组件使用起来非常简单,如果只想简单使用,按照下面的实例,即可实现:

    <template>
        <div style="border: 1px solid #ccc">
          <Toolbar
            style="border-bottom: 1px solid #ccc"
            :editor="editorRef"
            :defaultConfig="toolbarConfig"
            :mode="mode"
          />
          <Editor
            style="height: 500px; overflow-y: hidden;"
            v-model="valueHtml"
            :defaultConfig="editorConfig"
            :mode="mode"
            @onCreated="handleCreated"
          />
        div>
    template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    <script>
    import '@wangeditor/editor/dist/css/style.css' // 引入 css
    import { onBeforeUnmount, ref, shallowRef } from 'vue'
    import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
    
    export default {
      components: { Editor, Toolbar },
      setup() {
        // 编辑器实例,必须用 shallowRef
        const editorRef = shallowRef()
    
        // 内容 HTML
        const valueHtml = ref('')
        const toolbarConfig = {}
        const editorConfig = { placeholder: '请输入内容...' }
    
        // 组件销毁时,也及时销毁编辑器
        onBeforeUnmount(() => {
            const editor = editorRef.value
            if (editor == null) return
            editor.destroy()
        })
    
        const handleCreated = (editor) => {
          editorRef.value = editor // 记录 editor 实例,重要!
        }
    
        return {
          editorRef,
          valueHtml,
          mode: 'default', // 或 'simple'
          toolbarConfig,
          editorConfig,
          handleCreated
        };
      }
    }
    </script>  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    以上,即可实现最简单的富文本编辑功能,valueHtml 就是富文本编辑的内容,只需要使用 v-html 指令即可将其渲染。

    2. 配置菜单栏

    上面的实例很多功能不完善,只有最原始的功能,如果需要更加丰富的功能,需要对菜单栏进行自定义编辑。

    <template>
        <div class="edit">
          <Toolbar class="Toolbar" :editor="editorRef" :defaultConfig="toolbarConfig" :mode="mode" />
          <Editor class="Editor" :defaultConfig="editorConfig" :mode="mode" v-model="valueHtml" @onCreated="handleCreated" @customPaste="customPaste" />
        div>
    template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    三、自定义图片\视频上传功能

    自带图片上传功能文档

    自带的图片、视频上传服务可能无法 适用与真实的开发场景,所以对这一块的功能进行自定义是必然的。

    在同一页面公共地方写 editorConfig.MENU_CONF['uploadImage'] 方法,上传图片、视频时会自动触发,可以同时选择多张照片上传,图片会一张一张上传。

    // 自定义图片上传
    editorConfig.MENU_CONF['uploadImage'] = {
    	async customUpload(file, insertFn) {
    		let formData = new FormData();
    		formData.append('files', file);
    		try {
    			// 这里结合实际场景写自己上传图片的逻辑,此处代码仅为示例
    			const { data } = await upload(formData);
    			// 对图片进行处理,同样需要结合实际场景
    			data.forEach(item => {
    				insertFn(item, 'image', item)
    			})
    		} catch (error) {
    			console.log(error);
    		}
    	}
    }
    
    // 自定义视频上传
    editorConfig.MENU_CONF['uploadVideo'] = {
    	async customUpload(file, insertFn) {
    		let formData = new FormData();
    		formData.append('files', file);
    		try {
    			// 这里结合实际场景写自己上传图片的逻辑,此处代码仅为示例
    			const { data } = await upload(formData);
    			// 对图片进行处理,同样需要结合实际场景
    			data.forEach(item => {
    				insertFn(item, 'video')
    			})
    		} catch (error) {
    			console.log(error);
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    注意

    1. 图片无法控制具体宽度,只能按照比例确定宽度
    2. 图片默认为自身100%宽度,如需限制,可以在盒子外层使用 !important

    常见错误

    1. vue-router.mjs:3471 Error: Module build failed (from ./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/index.js): TypeError: Cannot read property 'content' of null
      在这里插入图片描述
      可能是 vue-loader 版本有问题,较低或较高都有可能;也有可能是写法有问题,建议仔细检查代码,这个问题在 ts 中很容易出现。

    四、复制粘贴功能

    这个功能原本就有,默认会携带格式,如需去除,可以对齐进行修改和限制。以下示例为粘贴纯文本,如果更多限制,可以自行改写。

    const customPaste = (editor, event, callback) => {
    	const text = event.clipboardData.getData('text/plain') // 获取粘贴的纯文本
    	if (text) {
    		editor.insertText(text)
    		event.preventDefault()
    		callback(false)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    如需作者补充或修改,欢迎在评论区留言。
    END

  • 相关阅读:
    麒麟信安受邀协办2023广电五舟行业交流大会,共建信创产业新生态
    Linux内核中竞态学习过程的问题
    java计算机毕业设计ssm党支部在线学习
    图神经网络入门(理论篇)
    Java反射详解
    Linux Kernel:调度器scheduler
    云桥通+跨境电商:SDWAN企业组网优化跨境网络案例
    怎么批量修改文件后缀名?
    DTCC 2023丨云原生环境下,需要什么样的 ETL 方案?
    MySQL的事务隔离是如何实现的?
  • 原文地址:https://blog.csdn.net/m0_53808238/article/details/133989583