富文本编辑器wangEdiotr报错Error in callback for watcher "value": "Error: Cannot find a descendant at path [0,2] in node

作者:admin 发布时间:2024-08-14 14:06:29 浏览:223次

富文本编辑器wangEdiotr作为vue组件使用时,上传图片后,再打开报错Error in callback for watcher "value": "Error: Cannot find a descendant at path [0,2] in node

原因是组件不显示时,没有及时把组件销毁,导致了冲突。

解决方法:

在引用组件时加上v-if="open",只要每次打开都重新渲染MyEditor组件就好了


<my-editor v-model="form.content" v-if="open"  />



完整的MyEditor封装组件代码如下:

<!--
 *                                                     __----~~~~~~~~~~~------___
 *                                    .  .   ~~//====......          __--~ ~~
 *                    -.            \_|//     |||\\  ~~~~~~::::... /~
 *                 ___-==_       _-~o~  \/    |||  \\            _/~~-
 *         __---~~~.==~||\=_    -_--~/_-~|-   |\\   \\        _/~
 *     _-~~     .=~    |  \\-_    '-~7  /-   /  ||    \      /
 *   .~       .~       |   \\ -_    /  /-   /   ||      \   /
 *  /  ____  /         |     \\ ~-_/  /|- _/   .||       \ /
 *  |~~    ~~|--~~~~--_ \     ~==-/   | \~--===~~        .\
 *           '         ~-|      /|    |-~\~~       __--~~
 *                       |-~~-_/ |    |   ~\_   _-~            /\
 *                            /  \     \__   \/~                \__
 *                        _--~ _/ | .-~~____--~-/                  ~~==.
 *                       ((->/~   '.|||' -_|    ~~-/ ,              . _||
 *                                  -_     ~\      ~~---l__i__i__i--~~_/
 *                                  _-~-__   ~)  \--______________--~~
 *                                //.-~~~-~_--~- |-------~~~~~~~~
 *                                       //.-~~~--\
 *                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * 
 *                               神兽保佑            永无BUG
 * 
 * @Description: 
 * @Author: 小超越
 * @AuthorBlog: www.zhe94.com
 * @Date: 2024-08-07 12:09:33
 * @LastEditors: 小超越 516761948@qq.com
 * @LastEditTime: 2024-08-14 11:47:22
 -->

<template>
    <div style="border: 1px solid #ccc;">
        <Toolbar style="border-bottom: 1px solid #ccc" :editor="editor" :defaultConfig="toolbarConfig" :mode="mode" />
        <Editor style="height: 500px; overflow-y: hidden;z-index:100;" v-model="html" :defaultConfig="editorConfig" :mode="mode"
            @onCreated="onCreated" 
            @onChange="onChange"
            />
    </div>
</template>
<script>
import Vue from 'vue'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { Boot } from '@wangeditor/editor'
import { getToken } from '@/utils/auth'
// class MyButtonMenu implements IButtonMenu {   // TS 语法
class MyButtonMenu {                       // JS 语法

    constructor() {
        this.title = '标题样式' // 自定义菜单标题
        // this.iconSvg = '<svg>...</svg>' // 可选
        // this.tag = 'button'
        this.tag = 'select'
        this.width = 80
       
    }
    // 下拉框的选项
    getOptions(editor) {
        let text = editor.getSelectionText() //选中文本
        const options = [
          { value: '', text: '标题样式', selected: true },
          { value: "<h3><span style='background-color: rgb(115, 209, 61);'>"+text+"</span></h3>", text: '绿色' },
          { value: "<h3><span style='background-color: rgb(235, 144, 58);'>"+text+"</span></h3>", text: '橙色' },
          { value: "<h3><span style='background-color: rgb(9, 109, 217);'>"+text+"</span></h3>", text: '蓝色' },
          { value: "<h3><span style='background-color: rgb(135, 56, 0);'>"+text+"</span></h3>", text: '咖啡色' },
          
        ]
        return options
    }

    // 获取菜单执行时的 value ,用不到则返回空 字符串或 false
    // getValue(editor: IDomEditor): string | boolean {   // TS 语法
    getValue(editor) {                              // JS 语法
        // console.log(editor.getSelectionText())
        // let text = editor.getSelectionText()
        // text = "<h2  style='width: 60%;color: #ffffff;display: block;text-align: center;margin: 30rpx auto 40rpx auto;border-radius: 50rpx;background: #636d36;font-size: 32rpx;padding: 15rpx 0;'>" + text + "</h2>"
        return ''
    }

    // 菜单是否需要激活(如选中加粗文本,“加粗”菜单会激活),用不到则返回 false
    // isActive(editor: IDomEditor): boolean {  // TS 语法
    isActive(editor) {                    // JS 语法
        return false
    }

    // 菜单是否需要禁用(如选中 H1 ,“引用”菜单被禁用),用不到则返回 false
    // isDisabled(editor: IDomEditor): boolean {   // TS 语法
    isDisabled(editor) {                     // JS 语法
        return false
    }

    // 点击菜单时触发的函数
    // exec(editor: IDomEditor, value: string | boolean) {   // TS 语法
    exec(editor, value) {                              // JS 语法
        if (this.isDisabled(editor)) return
        // editor.insertText(value) // value 即 this.value(editor) 的返回值
        // editor.dangerouslyInsertHtml('<div classname="title"">sjdlkfjsld</div>')
        console.log(value)
        editor.dangerouslyInsertHtml(value)
    }
   
   
   

}
const menu1Conf = {
    key: 'menu1', // 定义 menu key :要保证唯一、不重复(重要)
    factory() {
        return new MyButtonMenu() // 把 `YourMenuClass` 替换为你菜单的 class
    },
}
const models = { menus: [menu1Conf] }
Boot.registerModule(models)
export default Vue.extend({
    name: 'MyEditor',
    props:{
        value:{
            type:String
        }
    },
    components: { Editor, Toolbar },
    
    data() {
        return {
           
            mode: 'default', // or 'simple'
            editor: null,
            html: this.value,
            toolbarConfig: {
                insertKeys: {
                    index: 1, // 插入的位置,基于当前的 toolbarKeys
                    keys: ['menu1']
                }
            },
            editorConfig: {
                placeholder: '请输入内容...',
                MENU_CONF: {
                    // 配置上传图片
                    uploadImage: {
                        server: process.env.VUE_APP_BASE_API + '/file/upload', // 上传的图片服务器地址
                        // form-data fieldName,后端接口参数名称,默认值wangeditor-uploaded-image
                        fieldName: "file",
                        // 自定义增加 http  header
                        headers: {
                            Authorization: 'Bearer ' + getToken()
                        },   
                        //上传回调
                        customInsert: this.customInsert

                    }
                }
                
            }
        }
    },
    watch: {
        
    value: {
       
      handler(val) {
        console.log("拦截",val)
        if (val !== this.html && val !==null) {
          this.html = val === '' ? '' : val
          if (this.editor) {
            //  if(!this.editor.isFocused()){
            //     console.log("不聚焦编辑器")
            //     this.editor.focus()
            //  }
            //  console.log("进入设置内容")
                //重置内容
            // this.editor.setHtml(this.html)
            this.editor.clear()
            this.editor.dangerouslyInsertHtml(this.html);
          
          }
        }
        if(val===null){
            if(this.editor){
                console.log("进入清除")
                this.editor.clear()
            }
        }
      },
      immediate: true
    }
  },
    methods: {
      
        //创建
        onCreated(editor) {
            // console.log("获取html",this.html)
            // console.log('editor created!', editor.getHtml())
            console.log("创建")
            this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错
        
        },
        //内容回调
        onChange(editor) {
            // console.log(editor.getHtml())
            this.$emit("input", editor.getHtml());
        },
        //上传图片
        customInsert(res, insertFn) {                  // JS 语法
            // res 即服务端的返回结果
            let url = res.data.url // 图片 src ,必须
            let alt = res.data.name //图片描述文字,非必须
            let href = res.data.url // 图片的链接,非必须
            // 从 res 中找到 url alt href ,然后插入图片
            insertFn(url, alt, href)
        }
        
    },
    mounted() {
        this.html = this.value;
        // this.$nextTick(()=>{
        //     this.html=this.value
        // })
    },
    
    beforeDestroy() {
        const editor = this.editor
        if (editor == null) return
        editor.destroy() // 组件销毁时,及时销毁编辑器
    }
})
</script>
<style src="@wangeditor/editor/dist/css/style.css"></style>


如需转载请保留本文出处: https://zhe94.com/978.html

上一篇:懂懂日记:一点委屈
下一篇:NVM管理nodejs的多个版本
vs code 的常用快捷键

vs code 的常用快捷键

Visual Studio Code是个一款非常优秀的代码编辑工具,支持多种编程语言的编写。工具很常用,要想用得溜还得记记快捷键,把技巧记下来,编写代码大大提高工作效率,事半功倍。
Mysql关联表查询怎么样才能只取最新一条记录

Mysql关联表查询怎么样才能只取最新一条记录

有时我们使用mysql的时候想要多个表查询数据,但是关联查询的时候有多条记录,我们只想要最新的一条记录怎么办呢?很多人第一时间想到的是使用group by 处理,这是没问题的,但是需要提取做些处理,要是直接查询出来的数据可能并不准确。