当前位置: 首页 > 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.lryc.cn/news/621867.html

相关文章:

  • demo 通讯录 + 城市选择器 (字母索引左右联动 ListItemGroup+AlphabetIndexer)笔记
  • 分布式锁:从理论到实战的深度指南
  • 【机器人-基础知识】ROS常见功能架构
  • 微软自曝Win 11严重漏洞:可导致全盘数据丢失
  • Kafka生产者原理深度解析
  • 从ChatGPT到智能助手:Agent智能体如何颠覆AI应用
  • Python爬虫反爬检测失效问题的代理池轮换与请求头伪装实战方案
  • 【121页PPT】智慧方案智慧综合体智能化设计方案(附下载方式)
  • java + html 图片点击文字验证码
  • 结构体(Struct)、枚举(Enum)的使用
  • 电源测试系统ATECLOUD-Power,让您告别电源模块测试痛点!
  • MLOps已死,AgenticOps当立:构建新一代AI智能体的全新工程范式
  • 【Redis】Redis典型应用——分布式锁
  • 【部署K8S集群】 1、安装前环境准备配置
  • k8s1.28.2集群部署istioctl的1.20.0版本(X86架构)
  • Mac(一)常用的快捷键整理
  • Mac Mysql 卸载
  • 18- 网络编程
  • Java ArrayList的介绍及用法
  • 单片机闪烁灯实验
  • HDFS数据倾斜导致MapReduce作业失败的排查与优化实践
  • 3分钟解锁网页“硬盘“能力:离线运行VSCode的新一代Web存储技术
  • 【数据分享】2022 年黑龙江省小麦、玉米和水稻幼苗影像数据集
  • 经典回顾:Hive执行原理、MapReduce执行流程、Spark执行流程
  • 系统思考:情绪内耗与思维模式
  • 学习笔记与效率提升指南:编程、记忆与面试备考
  • 腾讯云开发小程序工具箱使用心得
  • LeetCode Hot100:递归穿透值传递问题
  • 三天速通 Vue+Flask+SQLite 项目+阿里云轻量应用级服务器【宝塔面板】①
  • 【Unity3D实例-功能-拔枪】角色拔枪(一)动态创建武器