Vue3 使用 富文本编辑器 wangeditor/editor-for-vue 配置详解

news2024/9/27 7:25:22

Vue3 使用 富文本编辑器 wangeditor/editor-for-vue 配置详解

先上官网地址 wangEditor 5 点这里

  1. wangeditor 主要API

配置功能栏


		let toolbarConfig = {
			toolbarKeys: [ 
					"bold", // 字体加粗 
					"underline", // 字体下划线 
					"italic", // 字体斜体 
					"through", // 字体删除线 
					"code", // 字体代码 
					"sub", // 下标 "sup", // 上标 
					"clearStyle", // 清除字体样式 
					"color", // 字体颜色 
					"bgColor", // 背景颜色 
					"fontSize", // 字体大小 
					"fontFamily", // 字体 
					// "indent", // 增加缩进 
					// "delIndent", // 减少缩进 
					// "justifyLeft", // 左对齐 
					// "justifyRight", // 右对齐 
					// "justifyCenter", // 居中对齐 
					// "justifyJustify", // 两端对齐 
					'|', // 分割线
					"lineHeight", // 行间距 
					"insertImage", // 插入图片 
					"deleteImage", // 删除图片 
					"editImage", // 编辑图片 
					"viewImageLink", // 查看图片链接 
					"imageWidth30", // 图片宽度30% 
					"imageWidth50", // 图片宽度50% 
					"imageWidth100", // 图片宽度100% 
					"divider", // 分隔线 
					"emotion", // 表情 
					"insertLink", // 插入链接 
					"editLink", // 编辑链接 
					"unLink", // 取消链接 
					"viewLink", // 查看链接 
					"codeBlock", // 代码块 
					"blockquote", // 引用块 
					'|',
					"headerSelect", // 头部类型选择 
					"header1", // 头部1 
					"header2", // 头部2 
					"header3", // 头部3 
					"header4", // 头部4 
					"header5", // 头部5 
					"todo", // 待办事项 
					"redo", // 重做 
					"undo", // 撤销 
					"fullScreen", // 全屏 
					"enter", // 换行 
					"bulletedList", // 无序列表 
					"numberedList", // 有序列表 
					"insertTable", // 插入表格 
					"deleteTable", // 删除表格 
					"insertTableRow", // 插入表格行 
					"deleteTableRow", // 删除表格行 
					"insertTableCol", // 插入表格列 
					"deleteTableCol", // 删除表格列 
					"tableHeader", // 表格标题 
					"tableFullWidth", // 表格全宽 
					// "insertVideo", // 插入视频 
					// "uploadVideo", // 上传视频 
					"editVideoSize", // 编辑视频大小 
					"uploadImage", // 上传图片 
					"codeSelectLang", // 选择代码语言 
					// 设置为下拉选择    ---------------------------------------   一下代码为下拉样式
					{
						key: 'group-video',
						title: '视频',  // 下拉名称
						iconSvg:
							'<svg viewBox="0 0 1024 1024"><path d="M981.184 160.096C837.568 139.456 678.848 128 512 128S186.432 139.456 42.816 160.096C15.296 267.808 0 386.848 0 512s15.264 244.16 42.816 351.904C186.464 884.544 345.152 896 512 896s325.568-11.456 469.184-32.096C1008.704 756.192 1024 637.152 1024 512s-15.264-244.16-42.816-351.904zM384 704V320l320 192-320 192z"></path></svg>',   // 下拉图标
						menuKeys: ['insertVideo', 'uploadVideo'],  // 插入视屏  // 视屏上传
					},
					'|',
							{
					key: 'group-justify',
					title: '对齐',
					iconSvg:
						'<svg viewBox="0 0 1024 1024"><path d="M768 793.6v102.4H51.2v-102.4h716.8z m204.8-230.4v102.4H51.2v-102.4h921.6z m-204.8-230.4v102.4H51.2v-102.4h716.8zM972.8 102.4v102.4H51.2V102.4h921.6z"></path></svg>',
					menuKeys: ['justifyLeft', 'justifyRight', 'justifyCenter', 'justifyJustify'], // 对齐的四种方式
				},
				{
					key: 'group-indent',
					title: '缩进',
					iconSvg:
						'<svg viewBox="0 0 1024 1024"><path d="M0 64h1024v128H0z m384 192h640v128H384z m0 192h640v128H384z m0 192h640v128H384zM0 832h1024v128H0z m0-128V320l256 192z"></path></svg>',
					menuKeys: ['indent', 'delIndent'], // 缩进的两种方式
				},
			]
		};

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

编辑器配置

	//编辑器配置
		let editorConfig = {
			placeholder: '请输入内容...', // 配置编辑器 placeholder
			readOnly: false, // 配置编辑器是否只读,默认为 false
			autoFocus: true, // 配置编辑器默认是否 focus ,默认为 true
			scroll: true, // 配置编辑器是否支持滚动,默认为 true
			maxLength: 1000,  // 最大输入length
			hoverbarKeys:{
			    'link': {
			        // 重写 link 元素的 hoverbar
			        menuKeys: ['editLink', 'unLink', 'viewLink'],
			    },
			    'image': {
			        // 清空 image 元素的 hoverbar
			        menuKeys: [],
			    }
			},
            onMaxLength:(editor)=>{
                 // 当达到 maxlength 限制时,触发该回调函数
            },
            onCreated: (editor) => {  
				// 编辑器创建完毕时的回调函数。
			},
			onChange: (editor) => {  
				// 编辑器内容、选区变化时的回调函数。
			},
			onDestroyed: (editor) => {  
				// 编辑器销毁时的回调函数。
			},
			onFocus: (editor) => {  
				// 编辑器 focus 时的回调函数。
			},
			onBlur: (editor) => {  
				// 编辑器 blur 时的回调函数。
			},
			customPaste: (editor) => {  
				// 编辑器 blur 时的回调函数。
			},
			customAlert: (s,t) => {  
				// 自定义编辑器 alert 
			}

			// 所有的菜单配置,都要在 MENU_CONF 属性下
			MENU_CONF: {
			    // 插入图片
				insertImage: {
					onInsertedImage(){
					
					},
				},
				// 配置上传图片
				uploadImage: {
					customUpload: (file, insertFn)=>{
                       // 上传图片的方法
                    },
				},
				// 配置上传视频
				uploadVideo: {
					customUpload:  (file, insertFn)=>{
                       // 上传视频的方法
                    },
				},
			},
		};

以上为基本常用的一些配置

  1. 使用方法

插件安装

	yarn add @wangeditor/editor
	# 或者 npm install @wangeditor/editor --save
	
	yarn add @wangeditor/editor-for-vue
	# 或者 npm install @wangeditor/editor-for-vue --save

组件封装

// 组件封装
// WangEditor.vue

<template>
	<div style="border: 1px solid #ccc" v-loading="loading" element-loading-text="文件上传中...">
		<div style="color: red; padding-left: 18px">注:视频最佳宽度700-900</div>
		<Toolbar style="border-bottom: 1px solid #ccc" class="count-yc-box-title" :editor="editorRef" :defaultConfig="toolbarConfig" :mode="mode" />

		<Editor
			style="min-height: 250px; overflow-y: hidden"
			v-model="valueHtml"
			:defaultConfig="editorConfig"
			:mode="mode"
			@onCreated="handleCreated"
			class="count-yc-box"
		/>
	</div>
</template>
<script>
//script标签中引入
import '@wangeditor/editor/dist/css/style.css'; // 引入 css
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
import { defineExpose, onMounted, watch } from 'vue';
import request from '@/utils/request';   // 这个是请求封装   请更换为你的地址
export default {
	components: { Editor, Toolbar },
	props: {
		editValue: {
			type: String,
			default: '',
		},
	},
	setup(props, { emit }) {
		emits: ['select'];
		// 编辑器实例,必须用 shallowRef
		const editorRef = shallowRef();
		console.log(editorRef, 'editor.getAllMenuKeys()');
		// 内容 HTML
		const valueHtml = ref('');
		const loading = ref(false);

		watch(
			() => props.editValue,
			(val) => {
				//当编辑器的内容发生变化时,把值传给父组件
				valueHtml.value = props.editValue;
			},
			{
				deep: true,
				immediate: true,
			}
		);
		//配置功能栏
		let toolbarConfig = {
			toolbarKeys: [
				'headerSelect',
				'header1',
				'header2',
				'header3',
				{
					key: 'group-video',
					title: '视频',
					iconSvg:
						'<svg viewBox="0 0 1024 1024"><path d="M981.184 160.096C837.568 139.456 678.848 128 512 128S186.432 139.456 42.816 160.096C15.296 267.808 0 386.848 0 512s15.264 244.16 42.816 351.904C186.464 884.544 345.152 896 512 896s325.568-11.456 469.184-32.096C1008.704 756.192 1024 637.152 1024 512s-15.264-244.16-42.816-351.904zM384 704V320l320 192-320 192z"></path></svg>',
					menuKeys: ['insertVideo', 'uploadVideo'],
				},
				'blockquote',
				'|',
				'bold',
				'underline',
				'italic',
				'lineHeight',
				{
					key: 'group-more-style',
					title: '更多',
					iconSvg:
						'<svg viewBox="0 0 1024 1024"><path d="M204.8 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z"></path><path d="M505.6 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z"></path><path d="M806.4 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z"></path></svg>',
					menuKeys: ['through', 'code', 'sup', 'sub'],
				},
				'color',
				'bgColor',
				'|',
				'fontSize',
				{
					key: 'group-justify',
					title: '对齐',
					iconSvg:
						'<svg viewBox="0 0 1024 1024"><path d="M768 793.6v102.4H51.2v-102.4h716.8z m204.8-230.4v102.4H51.2v-102.4h921.6z m-204.8-230.4v102.4H51.2v-102.4h716.8zM972.8 102.4v102.4H51.2V102.4h921.6z"></path></svg>',
					menuKeys: ['justifyLeft', 'justifyRight', 'justifyCenter', 'justifyJustify'],
				},
				'todo',
				'fontFamily',
				{
					key: 'group-indent',
					title: '缩进',
					iconSvg:
						'<svg viewBox="0 0 1024 1024"><path d="M0 64h1024v128H0z m384 192h640v128H384z m0 192h640v128H384z m0 192h640v128H384zM0 832h1024v128H0z m0-128V320l256 192z"></path></svg>',
					menuKeys: ['indent', 'delIndent'],
				},

				'|',
				'emotion',
				'insertLink',
				'uploadImage',
				'insertTable',
				'codeBlock',
				'divider',
				'clearStyle',
				'|',
				'undo',
				'redo',
			],
		};

		const uploadImageList = ref([]);
		const saveImageList = ref([]);

		//上传本地图片
		function update(file, insertFn) {
			let formData = new FormData();
			formData.append('file', file);
			loading.value = true;
			request({
				url: '/common/file/upload',
				headers: {
					'Content-Type': 'multipart/form-data',
				},
				method: 'post',
				timeout: 50000,
				data: formData,
			})
				.then((res) => {
					if (res.code === 200) {
						const src = res.data.fileUrl;
						insertFn(src, '百度 logo', src);
						loading.value = false;
					} else {
						loading.value = false;
					}
				})
				.catch(() => {
					loading.value = false;
				});
		}

		function getOnInsertedImage(imageNode) {
			uploadImageList.value.push(imageNode);
		}

		//编辑器配置
		let editorConfig = {
			placeholder: '请输入内容...',
			// 所有的菜单配置,都要在 MENU_CONF 属性下
			MENU_CONF: {
				insertImage: {
					onInsertedImage: getOnInsertedImage(),
				},
				// 配置上传图片
				uploadImage: {
					customUpload: update,
				},
				uploadVideo: {
					customUpload: update,
				},
			},
		};

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

		function copyObject(obj) {
			return JSON.parse(JSON.stringify(obj));
		}
		const handleCreated = (editor) => {
			editorRef.value = editor; // 记录 editor 实例,重要!
			saveImageList.value = editor.getElemsByType('image');
			uploadImageList.value = copyObject(saveImageList.value);
		};

		watch(
			() => valueHtml.value,
			() => {
				//当编辑器的内容发生变化时,把值传给父组件
				emit('select', valueHtml.value);
			}
		);
         
       // 一下方法 用作回调 但暂时未调用
		const handleChange = (editor) => {
			console.log('change:', editor.children);
		};
		const handleDestroyed = (editor) => {
			console.log('destroyed', editor);
		};
		const handleFocus = (editor) => {
			console.log('focus', editor);
		};
		const handleBlur = (editor) => {
			console.log('blur', editor);
		};
		const customAlert = (info, type) => {
			console.log(`【自定义提示】${type} - ${info}`);
		};
		const customPaste = (editor, event, callback) => {
			console.log('ClipboardEvent 粘贴事件对象', event);
			// const html = event.clipboardData.getData('text/html') // 获取粘贴的 html
			// const text = event.clipboardData.getData('text/plain') // 获取粘贴的纯文本
			// const rtf = event.clipboardData.getData('text/rtf') // 获取 rtf 数据(如从 word wsp 复制粘贴)

			// 自定义插入内容
			editor.insertText('xxx');

			// 返回 false ,阻止默认粘贴行为
			event.preventDefault();
			callback(false); // 返回值(注意,vue 事件的返回值,不能用 return)

			// 返回 true ,继续默认的粘贴行为
			// callback(true)
		};

		//父组件调用子组件的方法清空编辑器内容
		const abc = function () {
			valueHtml.value = '';
		};
		//暴露该方法,defineExpose要引入
		defineExpose({
			abc,
			valueHtml,
		});

		return {
			editorRef,
			valueHtml,
			mode: 'default', // 或 'simple'
			toolbarConfig,
			editorConfig,
			handleCreated,
			handleChange,
			handleDestroyed,
			handleFocus,
			handleBlur,
			customAlert,
			customPaste,
			abc,
			loading,
		};
	},
};
</script>

组件使用

<template>
    <el-form ref="ruleFormRef" :model="ruleForm" class="demo-ruleForm" label-width="80px">
      <el-form-item label="内容" prop="content" v-if="ruleForm.radio1 == 1" class="label-befor">
            <WangEditor class="WangEditor" @select="getRich" ref="childrenRef" :editValue="editValue" />
        </el-form-item>
    </el-form>
</template>
  
<script setup>
import { onMounted, reactive, ref, watch, nextTick } from 'vue'

import WangEditor from '@/custom/WangEditor.vue'

const props = defineProps({
  // 父页面传递的数据
    dataRow: {
        type: Object,
        default: () => {
            return { "title": "", "languageType": 1, "contentType": 1, "content": "", "remark": null }
        }
    },
})
const ruleFormRef = ref()
const ruleForm = reactive({
    content: "",
})
const editValue = ref("")

watch(props, (newUser, oldUser) => {
    if (props.dataRow && props.dataRow.id) {
      // 富文本回显
        ruleForm.content = props.dataRow.content
        editValue.value = ruleForm.content
    }
}, {
    deep: true,
    immediate: true
});

//当编辑器的内容更新时,获取该值
const getRich = function (value) {
    ruleForm.content = value
}
defineExpose({
    ruleForm,
})
</script>
  

上图
在这里插入图片描述

以上的代码封装 以及使用方法可直接复制使用 但需要修改你自己的上传接口。

以上就是wangeditor/editor-for-vue 基本配置详解,希望可以帮到您!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2104559.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一款用于分析java socket连接问题的工具

network-tools 介绍 network-tools基于sun jdk、Oracle jdk开发&#xff0c;拦截基于java socket请求&#xff0c;它包括 ​ http 客户端 ​ jdbc 客户端 ​ mq 客户端 ​ redis 客户端 目前提供如下功能&#xff1a; ​ 最近端点连接情况 ​ 最近与远程端点连接情况&am…

公寓项目(尚庭公寓笔记)

公寓项目 课程介绍项目概述移动端业务功能后台管理系统业务功能-公寓管理后台管理系统业务功能-租赁功能后台管理系统业务功能-系统管理&用户管理核心业务功能技术概述 项目开发流程项目原型数据库设计理论ER模型数据库设计流程 数据库设计实操概念模型逻辑模型公寓信息房间…

sse fetch-event-source插件的使用

sse简单介绍https://blog.csdn.net/weixin_42400404/article/details/141895877?csdn_share_tail%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22141895877%22%2C%22source%22%3A%22weixin_42400404%22%7D fetch-event-source gitHub地址 通信…

快速构建 AI 应用的利器:Python 库 Mesop

在当今这个 AI 技术飞速发展的时代&#xff0c;开发者们总是希望能够更快、更便捷地构建 AI 应用程序。今天&#xff0c;我要给大家介绍一个由 Google 推出的 Python 库——Mesop。它的出现&#xff0c;让我们能够轻松地搭建高效的 AI 应用。 Mesop 是什么&#xff1f; Mesop …

C#如何使用外部别名Extern alias

说到 extern 关键字&#xff0c;只是很简单告诉大家用来做区分两个不同 dll 有相同的命名空间和类&#xff0c;可以使用这个关键字。 在遇到了存在两个 dll 都有相同的命名空间&#xff0c;而且有相同的类的时候&#xff0c;如何同时使用这两个 dll 的类。 这里有两个库 Jall…

4.4SQL注入之布尔盲注

SQL注入之布尔盲注1.什么是布尔盲注&#xff1f; Web的页面的仅仅会返回True和False。那么布尔盲注就是进行SQL注入之后然后根据页面返回的True或者是False来得到数据库中的相关信息。 返回False时&#xff1a; 返回True时&#xff1a; 2.如何进行布尔盲注&#xff1f; 注入…

把空格对应的表头拼接起来

某Excel表格有表头&#xff0c;部分数据格为空。 ABCDEF1stat Astat Bstat Cstat Dstat Estat F2113XX4XXXX56XXX7XXXX8XX 要求处理每行&#xff0c;把空数据格对应的表头用斜线拼起来。 H1Summary2stat B/stat C/stat E/stat F/3stat C/stat D/stat F/4stat B/stat E/5stat…

冒泡排序及qsort函数

文章目录 前言一、冒泡排序二、qsort函数 前言 冒泡排序是一种简单的排序算法&#xff0c;它重复地遍历要排序的数列&#xff0c;一次比较两个元素&#xff0c;如果它们的顺序错误就把它们交换过来。遍历数列的工作是重复进行的&#xff0c;直到没有再需要交换的元素&#xff…

软考证书补贴动不动就好几万,真的能领到吗?

取得软考证书在许多地区都有补贴政策&#xff0c;从几千至二十几万元不等。有些考生会好奇这些补贴是真的能领到吗&#xff0c;为此&#xff0c;小希搜集了一些例子证明是可以领到的&#xff0c;供大家参考。 1、奖励名单里的软考证书 在一些地区公示的奖励名单里&#xff0c;…

SpringBoot使用入门

springboot基础 1. 项目创建(1) idea自动创建(2) 手动创建①创建普通maven项目② 引入springboot依赖 2. 配置文件使用(1) 配置文件格式(2) 配置文件书写(3) 值的获取 3. bean的管理(1) bean的扫描(2) bean的注册Bean注解Import注解 自定义组合注解减少配置类注解(3) 条件注册b…

vue3-scroll-seamless 大屏无缝滚动

npm install vue3-scroll-seamless --save //或者 yarn add vue3-scroll-seamless页面中引入 <template><div class"safety_item"><SoftwareHead title"高危及以上组件漏洞TOP10"></SoftwareHead><div class"table"…

python学习12:对txt/text类型的文件进行读写

1.对txt类型的文件进行读写 1&#xff09;对text文件的操作 打开文件-读/写文件-关闭文件 1.1)打开文件 open() 1.2)读/写文件 读: read(),readline(),rendlines() 写:write() 1.3)关闭文件 close() # 案例1:(读):moder # filename test004.txt # 同一个文件夹 filename rD:…

Unity之获取Avpro视频画面并在本地创建缩略图

一、效果 功能需求&#xff1a;获取StreamingAssets文件夹下的所有视频&#xff08;包含其子文件夹&#xff09;&#xff0c;获取指定时间的视频画面&#xff0c;然后将图片保存到本地磁盘中。 二、关于Avpro的事件监听 当指定视频时间进度时会触发FinishedSeeking&#xff0c…

[论文笔记]RAFT: Adapting Language Model to Domain Specific RAG

引言 今天带来一篇结合RAG和微调的论文&#xff1a;RAFT: Adapting Language Model to Domain Specific RAG。 为了简单&#xff0c;下文中以翻译的口吻记录&#xff0c;比如替换"作者"为"我们"。 本文介绍了检索增强微调(Retrieval Augmented Fine Tunin…

CNN-LSTM用于时间序列预测,发二区5分+没问题!

为了进一步提高时序预测的性能&#xff0c;研究者们组合了CNN和LSTM的特点&#xff0c;提出了CNN-LSTM混合架构。 这种架构因为独特的结构设计&#xff0c;能同时处理时空数据、提取丰富的特征、并有效解决过拟合问题&#xff0c;实现对时间序列数据的高效、准确预测&#xff…

跨平台RTSP播放器之VLC Media Player还是SmartPlayer?

好多开发者纠结&#xff0c;RTSP流播放&#xff0c;到底是用开源的VLC Media Player还是大牛直播SDK的SmartPlayer&#xff1f;针对此&#xff0c;本文做个简单的技术探讨&#xff0c;方便开发者根据实际需要&#xff0c;做适合自己场景的选择&#xff1a; VLC Media Player …

oracle 数据库 day0823

ok了家人们&#xff0c;今天学习了orcle的基本用法&#xff0c;一日不见&#xff0c;如隔三秋啊&#xff0c; 一.多表联合查询 和之前学习的MySQL数据库一样的用法&#xff0c; 1.1 笛卡尔积查询 SELECT * FROM A表,B表 查询员工表和部门表 select * from emp e, dept d; e…

虚拟系统VS

定义 虚拟系统VS&#xff08;Virtual System&#xff09;是指将一台物理设备PS&#xff08;Physical System&#xff09;虚拟成多个相互隔离的逻辑系统。每个VS独立工作&#xff0c;在业务功能上等同于一台独立的传统物理设备&#xff0c;如图2-1所示。 目的 随着网络规模的不…

PNAS亮点文章!浙江大学/东北林业大学/深圳华大生命科学研究院等联合揭示大熊猫种群演化历史,提出物种保护新见解!

本文首发于“生态学者”微信公众号&#xff01;作者投稿系列 全新世以来&#xff0c;尤其是工业革命以来&#xff0c;资源的过度开发利用和环境污染等人类活动&#xff0c;导致野生动物栖息地严重破碎化&#xff0c;甚至丧失&#xff0c;形成了大量隔离小种群&#xff0c;致使…

TESSY导入导出测试用例

TESSY支持测试用例的导入和导出&#xff0c;下面我们以tessy5.1为例&#xff0c;给大家展示。 1、导入测试用例 因为导入测试用例&#xff0c;需要先创建测试集&#xff0c;这部分不熟悉的&#xff0c;可以参考一下&#xff1a; https://blog.csdn.net/u012568663/article/det…