• wangeditor5在vue3中的全使用过程(图片上传、附件上传、工具栏配置、编辑器配置)


    1、参考官方的wangeditor5-for-vue3的开发手册

    官方文档地址:https://clinfc.github.io/wangeditor5-for-vue3/guide/

    说明为说明要编写这编博客文章?

    官方文档的使用手册对于新手来说比较的难看懂,写的也不够详细,源码的封装比较深。写博客的目的是为了详细讲解一个适合项目使用的wangeditor的基本全过程,适合直接复制使用和修改(原官方文档使用原生js编写)

    2、下载编辑器的依赖

    npm install @wangeditor/editor --save
    npm install @wangeditor/editor-for-vue@next --save
    
    # 下面是vue3单独的组件,上面两个是旧的
    
    npm install @wangeditor/editor wangeditor5-for-vue3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4L9P2FUX-1663476493749)(image/1、wangeditor依赖.png)]

    21.、新旧组件对比

    下面的组件只是作为一个对比,不详细讲

    旧组件

    根据看与编辑器分开封装组件

    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    新组件

    WeEditor 组件将 WeToolbarWeEditable 组件封装在了一个组件中,使用更方便。

    <template>
      <we-editor
        toolbar-class="toolbar"
        editable-class="editable"
        toolbar-style="border: 1px solid #d9d9d9"
        editable-style="border: 1px solid #d9d9d9"
        :toolbar-option="toolbar"
        :editable-option="editable"
        :toolbar-reloadbefore="onToolbarReloadBefore"
        :editable-reloadbefore="onEditableReloadBefore"
        v-model="formData.jarr"
        v-model:json="formData.jstr"
        v-model:html="formData.html"
      />
    </template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    3、入门使用组件

    创建一个新的vue页面来编写当前demo

    3.1、使用上面的新组件

    3.2、编写js代码

    <script>
    // 引入 wangeditor5 样式
    import '@wangeditor/editor/dist/css/style.css'
    
    import { WeEditor, useWangEditor } from 'wangeditor5-for-vue3'
    import { defineComponent, shallowReactive } from 'vue'
    export default defineComponent( {
    	name: "wangeditor",
    	components: { WeEditor },
    	setup() {
    		// 编辑器配置
    		const editableOption = {}
    
    		// 菜单栏配置
    		const toolbarOption = {}
    
    		// 防抖时长。当会触发重载的配置项发生变化 365ms 后,编辑器会重载
    		const reloadDelary = 365
    
    		// 对于上面的三个对象,经过 useWangEditor 处理后,返回的 editable 和 toolbar 分别对应编辑器和菜单栏的配置项
    		const { editable, toolbar } = useWangEditor(
    			editableOption,
    			toolbarOption,
    			reloadDelary
    		)
    
    		// 开启只读模式【不可编辑】
    		editable.config.readOnly = false
    
    		// 不要使用 reactive/ref,应该使用 shallowReactive/shallowRef 来接收 json array 数据
    		const formData = shallowReactive({ jarr: [], jstr: '', html: '' })
    
    		// 在可编辑的重新加载之前
    		function onEditableReloadBefore(inst) {
    			console.log(inst)
    			console.log('editable 即将重载: ' + new Date().toLocaleString())
    		}
    
    		// 在工具栏上重新加载之前
    		function onToolbarReloadBefore(inst) {
    			console.log(inst)
    			console.log('toolbar 即将重载: ' + new Date().toLocaleString())
    		}
    
    		return { editable, toolbar, formData, onEditableReloadBefore, onToolbarReloadBefore }
    	},
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    useWangEditor的官方说明

    经过 useWangEditor 处理后,返回的 editabletoolbar 分别对应编辑器菜单栏的配置项,不过此时的配置项对象具备了响应式特性,我们可以直接修改 editable/toolbar 对应属性来更新重载编辑器。

    如果传入的 editableOptiontoolbarOption 是响应式数据,内部将自动解除与之前的关联,也就意味着经过 useWangEditor 处理后得到的 editabletoolbar 配置对象,即使内容发生变化也不会触发之前的依赖更新!!!

    大白话:可以在useWangEditor之后的对象中编写,也可以直接在editableOption对象中编写好再进过useWangEditor处理,不建议各自写一点,因为会覆盖,要么在前面写要么在后面写

    3.3、编写样式

    原来组件上面通过 toolbar-style="border: 1px solid #d9d9d9"editable-style="border: 1px solid #d9d9d9"来指定了工具栏和编辑器的样式边框,通过查看DOM元素赋值如下

    <style>
    /*工具栏样式*/
    .toolbar{
    	border: 1px solid #d9d9d9;margin-bottom: 10px;
    }
    /*工具栏剧中显示*/
    .w-e-toolbar {
    	justify-content: center !important;
    }
    /*编辑器样式*/
    .editable{
    	border: 1px solid #d9d9d9;
    	min-height: 800px;
    	width: 850px;
    	margin: 30px auto 150px auto;
    	background-color: #fff;
    	box-shadow: 0 2px 10px rgb(0 0 0 / 12%);
    	border: 1px solid #e8e8e8;
    }
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    初始化效果

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b3znbMhl-1663476493750)(image/2、编辑器效果.png)]

    4、工具栏的修改(toolbarOption)

    关于工具栏的排序以及菜单的配置的获取,根据官网的语句通过vue方法获取我暂时没弄懂,所以通过原生的方式获取

    4.1、获取工具栏默认配置

    进入官方提供的Demo示例,按F12输入如下命令查看工具栏的默认配置

    toolbar.getConfig()
    
    • 1

    4.2、查看当前工具栏的默认配置

    toolbar.getConfig().toolbarKeys
    
    • 1

    4.3、查询编辑器注册的所有菜单 key (可能有的不在工具栏上)

    editor.getAllMenuKeys()
    
    • 1

    4.4、操作过程

    官方demo地址:https://www.wangeditor.com/demo/index.html

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sQDyZiVO-1663476493751)(image/3、浏览器查看配置.png)]

    4.5、工具栏模式对比及修改

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2bAWSN5C-1663476493751)(image/4、工具栏模式对比.png)]

    方式一,直接在菜单栏配置对象里面写

    // 菜单栏配置
    const toolbarOption = {
        mode: 'simple' // 指定简介模式
    }
    
    • 1
    • 2
    • 3
    • 4

    方式二、通过useWangEditor转换后的toolbar进行重新

    注意:后面的配置会覆盖前面的配置,所以当前设置的模式为default被后面所覆盖了

    默认配置建议在toolbarOption写好在通过useWangEditor转换

    // 对于上面的三个对象,经过 useWangEditor 处理后,返回的 editable 和 toolbar 分别对应编辑器和菜单栏的配置项
    const { editable, toolbar } = useWangEditor(
        editableOption,
        toolbarOption,
        reloadDelary
    )
    
    toolbar.mode = 'default'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    4.6、重新配置工具栏,显示哪些菜单,以及菜单的排序、分组

    根据上面的4.2步骤获取到了当前默认的工具栏配置如下,与工具栏一一对应

    [
        "headerSelect",
        "blockquote",
        "codeBlock",
        "|",
        "bold",
        "underline",
        "italic",
        {
            key: "group-more-style",
            title: "更多",
            iconSvg: "" +
                "" +
                "" +
                "" +
                "",
            menuKeys: ["through", "code", "sup", "sub", "clearStyle"]
        },
        "color",
        "bgColor",
        "|",
        "fontSize",
        "fontFamily",
        "lineHeight",
        "|",
        "bulletedList",
        "numberedList",
        "todo",
        {
            key: "group-justify",
            iconSvg: "",
            title: "对齐",
            menuKeys: ["justifyLeft", "justifyRight", "justifyCenter", "justifyJustify"]
        },
        {
            key: "group-indent",
            title: "缩进",
            iconSvg: "",
            menuKeys: ["indent", "delIndent"]
        },
        "|",
        "emotion",
        "insertLink",
        {
            key: "group-image",
            title: "图片",
            iconSvg: "",
            menuKeys: ["insertImage", "uploadImage"]
        },
        {
            key: "group-video",
            title: "视频",
            iconSvg: "",
            menuKeys: ["insertVideo", "uploadVideo"]
        },
        "insertTable",
        "divider",
        "|",
        "undo",
        "redo",
        "|",
        "fullScreen"
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    通过如下方法重新配置简介模式下的工具栏

    注意:如果想在useWangEditor处理后的toolbar对象修改,必须要在toolbarOption对象里面先创建空的一个config配置空对象后面才能修改到(来源一个网友的说法)

    // 菜单栏配置
    const toolbarOption = {
        mode: 'simple', // 指定简介模式
        config:{
            toolbarKeys:[
                "fontSize",'header1', 'header2', 'header3','header4','|',
                'blockquote',"code","codeBlock",'|',
                'bold', 'underline', 'italic', 'through', 'color', 'bgColor', 'clearStyle', '|',
                'bulletedList', 'numberedList', 'todo', 'justifyLeft','justifyCenter', 'justifyRight', '|',
                'insertLink',
                {
                    key: 'group-image',
                    title: '图片',
                    iconSvg: "",
                    menuKeys: ['insertImage', 'uploadImage']
                },
                "insertTable",
                "|",
                "undo","redo"
            ]
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    简洁效果如下

    后面再加入个附件上传的插件菜单

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EB3KioWj-1663476493752)(image/5、简洁排序.png)]

    5、菜单配置(editableOption)

    根据官网描述:wangEditor 从 V5 版本开始,工具栏配置和菜单配置(如配置颜色、字体、链接校验、上传图片等)分离了

    菜单配置是什么?就是上图中的选择默认字体大小类的内容,也就是工具栏的菜单功能实现

    5.1、查看编辑器配置

    可通过 editor.getConfig() 查看编辑器默认配置

    根据下图观察,editor后面使用的是getConfig是一个配置,所以下面的配置页要写在config对象里面

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2BL4YauT-1663476493752)(image/6、查看编辑器配置.png)]

    在4的步骤中使用editor.getAllMenuKeys()以及获取到了所有的菜单key,就可以进行下一步的菜单配置了

    5.2、配置默认字号

    如何查看keys和配置项?通过上图就可以看出对应的key,找到fontSize,点击进去就有fontSizeList数组了,根据里面的写法进行编写即可

    // 编辑器配置
    const editableOption = {
        config:{
            MENU_CONF:{
                fontSize:{
                    fontSizeList: [
                        // 元素支持两种形式
                        //   1. 字符串;
                        //   2. { name: 'xxx', value: 'xxx' }
                        '16px',
                        '20px',
                        { name: '26px', value: '26px' },
                        '40px',
                    ]
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    效果如下

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UvzFqXw0-1663476493753)(image/7、修改默认子号.png)]

    5.3、图片上传配置

    根据查询的ket查看如何配置

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tp0SN8B9-1663476493753)(image/8、查看上传图片配置.png)]

    实现

    我这里引入了ElementUI的插件所以可以使用this.$message.success(${file.name} 上传成功, res)作为提示

    后台的上传地址server需要自己编写能实现上传文件再进行测试

    官方上传文件的返回类型

    // 成功返回
    {
     "errno": 0, // 注意:值是数字,不能是字符串
     "data": {
         "url": "xxx", // 图片 src ,必须
         "alt": "yyy", // 图片描述文字,非必须
         "href": "zzz" // 图片的链接,非必须
     }
    }
    
    // 失败返回
    {
     "errno": 1, // 只要不等于 0 就行
     "message": "失败信息"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    我的是通过customInsert自定义返回类型

    // 编辑器配置
    const editableOption = {
        config:{
            placeholder:"请在这里输入内容...",
            MENU_CONF:{
                // 配置默认字号
                // 配置上传图片
                uploadImage:{
                    // 请求路径
                    server: "api/sysUser/uploadImg",
                    // 后端接收的文件名称
                    fieldName: "file",
                    maxFileSize: 1 * 1024 * 1024, // 1M
                    // 上传的图片类型
                    allowedFileTypes: ["image/*"],
                    // 小于该值就插入 base64 格式(而不上传),默认为 0
                    base64LimitSize: 10 * 1024, // 10MB
                    // 自定义插入返回格式【后端返回的格式】
                    customInsert(res, insertFn) {
                        if(res.code != 200 && res.success == false){
                            ElMessage.error("上传文件失败,"+res.message)
                            return
                        }
                        insertFn(res.data.url, res.data.alt, res.data.href)
                    },
                    // 携带的数据
                    meta: {
                        token: 'eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE2NjM0MjQ5MzEsInN1YiI6ImFkbWluIiwiaWF0IjoxNjYzNDIzMTMxOTAyfQ.McM6MZ6N9dQnAKym-9_TqAv6gjRWqf72Q4MTnMlS9AeIM-DhCjaJJrUMYbB8hs5r-HXYSXbs5O5pk9f_KUbGQg'
                    },
                    // 将 meta 拼接到 url 参数中,默认 false
                    metaWithUrl: true,
                    // 单个文件上传成功之后
                    onSuccess(file, res) {
                        if(res.code == 200 && res.success){
                            ElMessage.success(`${file.name} 上传成功`)
                            return
                        }else {
                            ElMessage.warning(`${file.name} 上传出了点异常`)
                            return
                        }
                        // console.log(`${file.name} 上传成功`, res)
                        //ElMessage.success(`${file.name} 上传成功`, res)
                    },
                    // 单个文件上传失败
                    onFailed(file, res) {
                        console.log(res)
                        ElMessage.error(`${file.name} 上传失败`)
                    },
                    // 上传错误,或者触发 timeout 超时
                    onError(file, err, res) {
                        console.log(err, res)
                        ElMessage.error(`${file.name} 上传出错`)
                    },
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    测试结果

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hh8k4mhB-1663476493754)(image/9、图片上传.png)]

    5.4、视频上传

    目前没有搞过,以后研究

    6、上传附件插件使用

    官方插件地址:https://github.com/wangeditor-team/wangEditor-plugin-upload-attachment

    6.1、下载依赖

    1. 安装yarn

      npm install --global yarn
      # 检查是否成功
      yarn --version
      
      • 1
      • 2
      • 3
    2. 安装插件依赖

      这是官网指定的,里面同时也包含了wangeditor5的全套依赖,使用的是yarn进行管理

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cMCaKgfA-1663476493755)(image/10、yarn'.png)]

      yarn add @wangeditor/plugin-upload-attachment
      
      • 1

      跟着上面步骤走的就通过下面的方式获取到(原先已近下载了其他依赖)

      npm i @wangeditor/plugin-upload-attachment -s
      
      • 1
    3. 查看

      在这里插入图片描述

    6.2、【注意】该文档要求 @wangeditor/editor 版本 >=5.1.16

    6.3、注册到编辑器

    import { Boot } from '@wangeditor/editor'
    import attachmentModule from '@wangeditor/plugin-upload-attachment'
    import { WeEditor, useWangEditor } from 'wangeditor5-for-vue3'
    
    // 注册。要在创建编辑器之前注册,且只能注册一次,不可重复注册。
    Boot.registerModule(attachmentModule)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在app.vue里面就能实现一次的注册

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p7bSA52j-1663476493755)(image/14、注册按钮.png)]

    6.4、编辑器配置上传附件菜单

    注意:如果在useWangEditor处理后的editable使用也需要在editableOptionconfig.MENU_CONF.uploadAttachment的空对象

    我是一类ElementUI的消息提示组件,如果复制那一段可能编译报错,自己修改

    // 编辑器配置
    const editableOption = {
      config:{
        hoverbarKeys: {
          attachment: {
            menuKeys: ['downloadAttachment'], // “下载附件”菜单
          },
        },
        MENU_CONF: {
          	// 上传附件
            uploadAttachment:{
                server: 'http://localhost:8081/api/sysUser/blogFileUpload',
                fieldName: 'file',
                maxFileSize: 100 * 1024 * 1024, // 100M
                // 携带的数据
                meta: {
                    token: 'eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE2NjM0MTQ1MjAsInN1YiI6ImFkbWluIiwiaWF0IjoxNjYzNDEyNzIwMDE5fQ.nFAEtMqduzValgDAsMUXeM0OSIlYK4hi8cjTSAL52jMgFwfuOUVNEbdT91abs1rdNXKjEtrymbn_2aO1Q2h26Q'
                },
                // 在上传之前
                onBeforeUpload(file) {
                    console.log('onBeforeUpload', file)
                    return file // 上传 file 文件
                    // return false // 会阻止上传
                },
                // 关于进展
                onProgress(progress) {
                    console.log('onProgress', progress)
                },
                // 成功回调
                onSuccess(file, res) {
                    if(res.errno === 0){
                        ElMessage.success(`${file}附件上传成功`)
                    }
                },
                // 失败回调
                onFailed(file, res) {
                    if(res.errno === 1){
                        ElMessage.success(`${file}附件上传失败,`+res.message)
                    }
                },
                // 错误
                onError(file, err, res) {
                    console.error('onError', file, err, res)
                },
    
                // // 上传成功后,用户自定义插入文件
                // customInsert(res: any, file: File, insertFn: Function) {
                //   console.log('customInsert', res)
                //   const { url } = res.data || {}
                //   if (!url) throw new Error(`url is empty`)
    
                //   // 插入附件到编辑器
                //   insertFn(`customInsert-${file.name}`, url)
                // },
    
                // // 用户自定义上传
                // customUpload(file: File, insertFn: Function) {
                //   console.log('customUpload', file)
    
                //   return new Promise(resolve => {
                //     // 插入一个文件,模拟异步
                //     setTimeout(() => {
                //       const src = `https://www.w3school.com.cn/i/movie.ogg`
                //       insertFn(`customUpload-${file.name}`, src)
                //       resolve('ok')
                //     }, 500)
                //   })
                // },
    
                // // 自定义选择
                // customBrowseAndUpload(insertFn: Function) {
                //   alert('自定义选择文件,如弹出图床')
                //   // 自己上传文件
                //   // 上传之后用 insertFn(fileName, link) 插入到编辑器
                // },
                // 插入到编辑器后的回调
                onInsertedAttachment(elem) {
                    console.log(elem)
                }
            },
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

    6.5、工具栏插件附件按钮

    方式一

    const toolbarOption = {
        config:{
            // 插入哪些菜单
            insertKeys: {
                index: 0, // 自定义插入的位置
                keys: ['uploadAttachment'], // “上传附件”菜单
            },
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    方式二

    uploadAttachment就是附件的key

    const toolbarOption = {
        config:{
            // 插入哪些菜单
            toolbarKeys:[
            	"fontSize",'header1', 'header2', 'header3','header4','|',
    			'blockquote',"code","codeBlock",'uploadAttachment','|',
    			....
            ]
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    6.6、后端数据响应格式

    成功

    {
      "errno": 0,
      "data": {
        "url": "附件的下载链接"
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    失败

    {
      "errno": 1,
      "message": "错误信息"
    }
    
    • 1
    • 2
    • 3
    • 4

    编辑器响应插入的标签

    <a data-w-e-type="attachment" data-w-e-is-void data-w-e-is-inline href="https://xxx.com/aaa/bbb/xxx.zip" download="xxx.zip">xxx.zipa>
    
    • 1

    6.7、上传附件测试

    需要自己编辑后端接口,并启动按照响应格式返回(文件会直接下载,图片打开一个新的窗口查看,再自行按需保存)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dEuVFFKc-1663476493756)(image/13、上传附件.png)]

    点击附件出现内容的关键是

    hoverbarKeys: {
      attachment: {
        menuKeys: ['downloadAttachment'], // “下载附件”菜单
      },
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5

    7、模型双向绑定

    WeEditable/WeEditor/WeEditorPlus 组件同时支持 v-modelv-model:jsonv-model:html 三种形式的双向绑定,分别对应 json arrayjson stringhtml string 三种格式的数据。

    注意事项:

    • 注意 WeEditableOption.extendCache 可能存在的影响!!!
    • 当我们进行 v-model 绑定时,推荐使用 shallowReactive/shallowRef 来缓存 json array 数据。如果你执意使用 reactive/ref 进行数据缓存,那么在出现未知错误时你可能找不到问题所在。
    • 在提交表单前,或手动触发表单验证前,请使用 syncContent 来强制同步 v-model 数据,避免数据不一致。
    • 双向绑定多个同时使用时,存在 v-model > v-model:json > v-model:html 的优先级关系。即:如果你使用优先级低的来设置数据的话,设置将被拦截(设置无效)。

    最优搭配为 v-html:jsonv-model:json + v-model:htmlv-model:json 相对 v-model 而言,能减少大量内存消耗和计算消耗。

    7.1、获取数据

    useWangEditor处理后的时候一个syncContent,才能使获取到的数据同步,返回submit方法,给按钮绑定点击事件调用即可

    setup() {
    	....
        // 对于上面的三个对象,经过 useWangEditor 处理后,返回的 editable 和 toolbar 分别对应编辑器和菜单栏的配置项
        const { editable, toolbar ,syncContent } = useWangEditor(
            editableOption,
            toolbarOption,
            reloadDelary,
            {
                delay: 3000, // 无操作 3s 后才会同步表单数据
                config: {
                    placeholder: '表单提交前使用 syncContent API 强制同步数据,确保数据不被丢失',
                },
            }
        )
    	// 获取数据
        const formData = shallowReactive({ html: '' })
        ....
    	// 表单提交
        function submit() {
            // 强制同步 v-model 数据
            syncContent()
            // 表单验证
            if(formData.html!=''){
                // TODO 进行业务处理
                ElMessage.success(formData.html)
            }else {
                ElMessage.error("请在编辑器内编写内容...")
            }
        }
    
        return { editable, toolbar, formData, submit,onEditableReloadBefore, onToolbarReloadBefore }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    获取到的数据后就可以在仅一步处理数据编写正常的业务流程了

  • 相关阅读:
    Skydel GNSS仿真引擎助力多所高校实现GNSS仿真测试教育
    在 kubernetes 环境下如何优雅扩缩容 Pulsar
    Java中Map.keySet()方法具有什么功能呢?
    Docker:01 OverView
    尚硅谷Redis6从入门到精通
    docker的数据管理
    LSKNet:大选择核网络在遥感目标检测中的应用
    ssm+vue的图书管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。
    Visual Subst – 突破常规,让虚拟驱动器 SUBST 无处不挂!
    Docker一键快速私有化部署(Ollama+Openwebui) +AI大模型(gemma,llama2,qwen)20240417更新
  • 原文地址:https://blog.csdn.net/baidu_39378193/article/details/126916335