当前位置: 首页 > news >正文

vue3 wangeditor5 编辑器,使用方法

针对于vue3,如果你也是遇到了这些问题,直接使用下面的方法可以完美解决
问题1:Cannot read properties of null (reading 'emitsOptions') 

问题2:使用 wangeditor 时报错 Uncaught (in promise) TypeError: Cannot read properties of null (reading 'emitsOptions') 和 Uncaught (in promise) Error: Cannot find a descendant at path [2] in node: {"children":[{"type":"paragraph","children":

问题3:自定义按钮报错,这种是重复注册的问题
Duplicated key 'customInsertImage' in menu items





进入正题直接可以使用下面的代码和方法,
vue3

"@wangeditor/editor": "^5.1.23",

"@wangeditor/editor-for-vue": "^5.1.12",

首先自建个组件,wangEditorCom.vue,可直接使用下面代码

<template><div><!-- 工具栏 --><Toolbar:editor="editorRef":defaultConfig="toolbarConfig":mode="'default'"style="border: 1px solid #ccc"/><!-- 编辑器 --><Editorv-model="valueHtml":defaultConfig="editorConfig":mode="'default'"style="height: 300px; border: 1px solid #ccc; overflow-y: auto;"@onCreated="handleCreated"/><!--这个是弹窗,可以改成自己的  --><!-- <ResourceSelectorv-model="resourceStore.showResourceDialog"title="从资源库选择图片":multiple="false":accept="['image']"ref="resourceSelectorRef"@confirm="handleResourceConfirm"/>--></div></template><script setup>import '@wangeditor/editor/dist/css/style.css'import { ref, onBeforeUnmount } from 'vue'import { Editor, Toolbar } from '@wangeditor/editor-for-vue'//弹窗//import ResourceSelector from '../components/ResourceSelector.vue//这里使用的是pinia,可以改成自己的import { useResourceStore } from '../stores/resource'const resourceStore = useResourceStore()// end 这里使用的是piniaconst resourceSelectorRef = ref(null)// 2. 编辑器数据const valueHtml = ref('<p>这里是</p>')const editorRef = ref(null)const toolbarConfig = {insertKeys: {index: 0, // 插到最前keys: ['|', 'customInsertImage']}}const editorConfig = {placeholder: '请输入内容...',MENU_CONF: {insertImage: {onInsertedImage(imageNode) {console.log('已插入网络图片', imageNode)},checkImage(src) {return /^https?:\/\//.test(src) // 只允许 http/https}},uploadImage: {//图片服务地址,可以改成自己的server: '/api/upload',fieldName: 'file',maxFileSize: 5 * 1024 * 1024,allowedFileTypes: ['image/*']}}}const handleCreated = (editor) => {//一定要这样Object.seal加这个,不然会报错editorRef.value = Object.seal(editor)}
//这是弹窗的回调事件,resource,const handleResourceConfirm = (resource) => {if (resource) {//插入图片,全局的一个editor,是在main里面注册的if (window.editor) {window.editor.dangerouslyInsertHtml(`<img src="${resource[0].url}" alt="" />`)}}}onBeforeUnmount(() => {
//一定要销毁if (editorRef.value) {editorRef.value.destroy()}})
//这里是父页面给子页面赋值用的defineExpose({valueHtml,})</script>

然后建立一个editorMenus.js,自定义toobar按钮,不需要自定义按钮的话,直接跳到最后使用

// editorMenus.js
import { Boot } from '@wangeditor/editor'
import { useResourceStore } from '../stores/resource'
// 自定义菜单配置
export const InsertImgMenuConf = {
//key值要和,wangEditCom.vue里面的 toolbarConfig配置的对应key: 'customInsertImage',factory() {return {title: '插入图片',iconSvg:'<svg viewBox="0 0 1024 1024" width="16" height="16"><path d="M896 160H128c-35.2 0-64 28.8-64 64v576c0 35.2 28.8 64 64 64h768c35.2 0 64-28.8 64-64V224c0-35.2-28.8-64-64-64zM128 800V224h768v288l-160-160-256 256-128-128-224 224z"/></svg>',tag: 'button',getValue() { return '' },isActive() { return false },isDisabled(editor) { return editor.isDisabled() },exec(editor) {if (this.isDisabled(editor)) return//全局保存editor实例window.editor = editor//使用pinia打开资源库弹窗const resourceStore = useResourceStore()resourceStore.showResourceDialog = true},}},
}// 全局只注册一次
if (!window.__hasRegisteredCustomInsertImage) {Boot.registerMenu(InsertImgMenuConf)window.__hasRegisteredCustomInsertImage = true
}

再然后pinia,

//这里是弹窗关闭和显示
import { defineStore } from 'pinia'export const useResourceStore = defineStore('resource', {state: () => ({showResourceDialog: false})
})

再然后main.js
直接引用   自己放置的目录 import ../utils/editorMenus.js

最后使用如下,因为我的是在form表单里面,下面例子可以直接使用

<template><el-button type="success" @click="handleAdd">新增动态</el-button>
<el-table :data="newsList" style="width: 100%">
<el-table-column  type="index" width="80" />
<el-table-column  prop="title" label="标题" width="80" />
<el-table-column label="操作" width="200"><template #default="scope"><el-button size="small" type="primary" @click="handleEdit(scope.row)">编辑</el-button></template></el-table-column></el-table><!--destroy-on-close   这个一定要加,这是弹窗销毁事件,不加会报错的-->
<el-dialogv-model="dialogVisible":title="dialogTitle"width="60%"@close="resetForm"destroy-on-close>
<el-form :model="form"  ref="formRef" label-width="100px"><el-form-item label="标题" prop="title"><el-input v-model="form.title" placeholder="请输入标题" /></el-form-item>
<el-form-item label="内容" prop="description"><wangEditcom ref="wangEditcomRef" /></el-form-item>
<template #footer><span class="dialog-footer"><el-button @click="dialogVisible = false">取消</el-button><el-button type="primary" @click="handleSubmit">确定</el-button></span></template>
</el-dialog></<template>
<script setup>
import { ref, reactive, onMounted, onBeforeUnmount, shallowRef, nextTick } from 'vue'
import wangEditcom from '../views/wangEditcom.vue'
const wangEditcomRef = ref(null)
const formRef= ref(null)
const newsList=ref({
[id:1,title:"晚上嗯"]
})
const form=ref(null)
// 对话框相关
const dialogVisible = ref(false)
const dialogTitle = ref('新增')const handleAdd = () => {dialogTitle.value = '新增'dialogVisible.value = true
}
const handleEdit = (row) => {dialogTitle.value = '编辑'Object.assign(form, row)dialogVisible.value = true nextTick(() => {if (wangEditcomRef.value) {wangEditcomRef.value.valueHtml = row.description || '<p>请输入内容...</p>'}})
}
const handleSubmit=()=>{
newsList.push(...form.value)
}
</script>

http://www.dtcms.com/a/332814.html

相关文章:

  • 非极大值抑制(NMS)详解:目标检测中的“去重神器”
  • 基于 Vue2+Quill 的富文本编辑器全方案:功能实现与样式优化
  • 列式存储与行式存储:核心区别、优缺点及代表数据库
  • Flink Stream API 源码走读 - map 和 flatMap
  • ETH持续上涨推动DEX热潮,交易活跃度飙升的XBIT表现强势出圈
  • MySQL 全面指南:从入门到精通——深入解析安装、配置、操作与优化
  • 从阻塞到异步:Java IO 模型进化史 ——BIO、NIO、AIO 深度解析
  • Cherryusb UAC例程对接STM32 SAI播放音乐和录音(下)=>USB+SAI+TX+RX+DMA控制WM8978播放和录音实验
  • 【嵌入式FreeRTOS#补充1】临界区
  • K-means 聚类算法学习笔记
  • 解锁PostgreSQL专家认证增强驱动引擎
  • 打靶日常-sql注入(手工+sqlmap)
  • 136-基于Spark的酒店数据分析系统
  • Python Sqlalchemy数据库连接
  • 紫金桥RealSCADA:国产工业大脑,智造安全基石
  • 【已解决】在Spring Boot工程中,若未识别到resources/db文件夹下的SQL文件
  • JavaScript 防抖(Debounce)与节流(Throttle)
  • 易道博识康铁钢:大小模型深度融合是现阶段OCR的最佳解决方案
  • 【Trans2025】计算机视觉|UMFormer:即插即用!让遥感图像分割更精准!
  • Notepad++插件开发实战指南
  • Radar Forward-Looking Imaging Based on Chirp Beam Scanning论文阅读
  • 《WINDOWS 环境下32位汇编语言程序设计》第1章 背景知识
  • 【Linux】探索Linux虚拟地址空间及其管理机制
  • C# HangFire的使用
  • 概率论基础教程第2章概率论公理(习题和解答)
  • 在 Linux 服务器搭建Coturn即ICE/TURN/STUN实现P2P(点对点)直连
  • HarmonyOS 实战:用 @Observed + @ObjectLink 玩转多组件实时数据更新
  • pyecharts可视化图表-pie:从入门到精通(进阶篇)
  • Python 数据可视化:柱状图/热力图绘制实例解析
  • 概率论基础教程第2章概率论公理