首页 前端知识 Vue3 使用 富文本编辑器 wangeditor/editor-for-vue 配置详解

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

2024-09-29 22:09:02 前端知识 前端哥 820 806 我要收藏

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 基本配置详解,希望可以帮到您!

转载请注明出处或者链接地址:https://www.qianduange.cn//article/18775.html
标签
评论
发布的文章

安装Nodejs后,npm无法使用

2024-11-30 11:11:38

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!