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

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.xdnf.cn/news/17901.html

相关文章:

  • 高并发场景下限流算法对比与实践指南
  • 【递归、搜索与回溯算法】DFS解决FloodFill算法
  • whisper 语种检测学习笔记
  • 39 C++ STL模板库8-容器1-array
  • 解决hexo deploy报错:fatal: bad config line 1 in file .git/config
  • 跨网络 SSH 访问:借助 cpolar 内网穿透服务实现手机远程管理 Linux
  • 图像识别控制技术(Sikuli)深度解析:原理、应用与商业化前景
  • Vue 组件二次封装透传slots、refs、attrs、listeners
  • 把 AI 装进“冰箱贴”——基于超低功耗语音合成的小屏电子价签
  • StringBoot-SSE和WebFlux方式消息实时推送-默认单向-可增加交互接口
  • C语言中的输入输出函数:构建程序交互的基石
  • 开源数据发现平台:Amundsen Frontend Service 应用程序配置
  • 基于CodeBuddy的2D游戏开发实践:炫酷大便超人核心机制解析
  • NOI Online培训1至26期例题解析(16-20期)
  • week1-[一维数组]传送
  • MySQLl中OFFSET 的使用方法
  • PIDGenRc函数中lpstrRpc的由来和InitializePidVariables函数的关系
  • JMeter性能测试详细版(适合0基础小白学习--非常详细)
  • 基于SpringBoot的救援物资管理系统 受灾应急物资管理系统 物资管理小程序
  • 浏览器环境下AES-GCM JavaScript 加解密程序
  • Elasticsearch ABAC 配置:实现动态、细粒度的访问控制
  • 【C#】跨平台创建你的WinForms窗体应用(WindowsUbuntu)
  • 新手入门 Makefile:FPGA 项目实战教程(一)
  • Java面试场景题大全精简版
  • vue3使用leaflet地图
  • 力扣(LeetCode) ——225 用队列实现栈(C语言)
  • 算法基础 第3章 数据结构
  • C++类与对象核心知识点全解析(中)【六大默认成员函数详解】
  • P1281 [CERC1998] 书的复制
  • TCP 连接管理:深入分析四次握手与三次挥手