vue2实现wangEditor富文本便捷器的封装使用--真实项目

基于wangEditor 5实现一个简单的富文本编辑器组件,实现自定义上传图片。

官网地址:https://www.wangeditor.com/v5/for-frame.html#%E9%85%8D%E7%BD%AE

1. 安装依赖包:

npm i @wangeditor/editor --save
npm i @wangeditor/editor-for-vue --save

2. 封装组件代码:

<template>
    <div class="editor-wrapper">
        <toolbar
            :editor="editor"
            :default-config="toolbarConfig"
            :mode="mode"
        />
        <editor
            v-model="html"
            :style="{height: height + 'px'}"
            :default-config="editorConfig"
            :mode="mode"
            @onCreated="onCreated"
            @onChange="onChange"
        />
        <div v-if="maxlength" class="useful-num">
            {{ useLen }}/{{ maxlength }}
        </div>
    </div>
</template>

<script>
import fileApi from '@/api/file';
import '@wangeditor/editor/dist/css/style.css';
import {Editor, Toolbar} from '@wangeditor/editor-for-vue';

export default {
    name: 'customEditor',
    components: {
        Editor,
        Toolbar
    },
    model: {
        prop: 'value',
        event: 'change'
    },
    props: {
        value: {
            type: String,
            default: ''
        },
        maxlength: {
            type: Number,
            default: 0
        },
        height: {
            type: [String, Number],
            default: 300
        }
    },
    watch: {
        value(val) {
            this.html = val;
        }
    },
    data() {
        return {
            editor: null,
            html: '',
            toolbarConfig: { },
            editorConfig: {
                placeholder: '请输入内容',
                MENU_CONF: {
                    uploadImage: {
                        // 自定义图片上传功能
                        customUpload: (resultFile, insertImgFn) => {
                            const formData = new FormData();
                            formData.append('file', resultFile);
                            // 将文件上传至服务器,res.data返回服务器存放文件的url
                            fileApi.postFileUpload(formData).then(res => {
                                // 插入图片,三个参数分别对应,url alt href
                                insertImgFn(res.data, '', res.data);
                            });
                        }
                    },
                    uploadVideo: {
                        // 自定义视频上传功能
                        customUpload: (resultFile, insertImgFn) => {
                            const formData = new FormData();
                            formData.append('file', resultFile);
                            // 将文件上传至服务器,res.data返回服务器存放文件的url
                            fileApi.postFileUpload(formData).then(res => {
                                // 插入视频,三个参数分别对应,url alt href
                                insertImgFn(res.data, '', res.data);
                            });
                        }
                    }
                }
            },
            mode: 'default', // or 'simple'
            useLen: 0
        };
    },
    methods: {
        onCreated(editor) {
            this.editor = Object.seal(editor); // 一定要用 Object.seal() ,否则会报错
        },
        onChange() {
            const text = this.editor.getText();
            // 计算当前输入了多少文字
            this.useLen = (text || '').length;
            // 每次富文本内容改变,触发change事件
            this.$emit('change', this.html);
        }
    },
    beforeDestroy() {
        // editor销毁
        const editor = this.editor;
        if (editor == null) {
            return;
        }
        editor.destroy();
    }
};
</script>

<style lang="scss" scoped>
    .editor-wrapper{
        z-index: 3;
        position: relative;     
        /deep/.w-e-toolbar{
            z-index: 2!important;
            border: solid 1px #E6E9EC!important;
            border-top-left-radius: 6px;
            border-top-right-radius: 6px;
            .w-e-bar-item{
                padding: 1px;
            }
        }
        /deep/.w-e-text-container{
            z-index: 1!important;
            border: solid 1px #E6E9EC!important;
            border-top: none!important;
            border-bottom-left-radius: 6px;
            border-bottom-right-radius: 6px;
        }
    }
    .useful-num{
        position: absolute;
        right: 6px;
        bottom: 10px;
        z-index: 99999;
        font-size: 12px;
        color: $text-3;
        background: #fff;
        padding: 0 6px;
        height: 28px;
        line-height: 28px;
    }
</style>

3. 父组件使用:

<template>
    <editor
        v-model="html"
        :maxlength="8192"
        @change="change"
    />
</template>

<script>
import Editor from '@/components/Editor';
export default {
    name: 'EditorExample',
    components: {
        Editor
    },
    data() {
        return {
            html: ''
        };
    },
    methods: {
        change(val) {
            console.log(val);
        }
    }
};
</script>

4. 真实项目使用:

封装了wangEditor富文本组件,并且设置了数据回显;

TextRich/index.vue

<template>
  <div style="border: 1px solid #ccc; width: 100%">
    <Toolbar style="border-bottom: 1px solid #ccc" :editor="editor" :defaultConfig="toolbarConfig" :mode="mode" />
    <Editor
      style="height: 500px; overflow-y: hidden"
      v-model="html"
      :defaultConfig="editorConfig"
      :mode="mode"
      @onCreated="handleCreated"
      @onChange="handleChange"
    />
  </div>
</template>
<script>
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { DomEditor } from '@wangeditor/editor'
import { set } from 'vue'
export default {
  components: {
    Editor,
    Toolbar
  },
  props: {
    value: {
      type: String,
      default: ''
    }
  },
  watch: {
    value(val) {
      setTimeout(()=>{
        this.html = val
      }, 1000)
    }
  },

  data() {
    return {
      editor: null,
      html: '',
      mode: 'default',
      editorConfig: {
        // placeholder: '请输入内容...',
        backColor: 'red', // 背景颜色
        MENU_CONF: {
          // 配置上传图片
          uploadImage: {
            customUpload: this.uploaadImg
          },
          uploadVideo: {
            customUpload: this.uploaadVideo
          }
        }
      },
      toolbarConfig: {}
    }
  },
  mounted() {
    // // 模拟 ajax 请求,异步渲染编辑器
    // setTimeout(() => {
    //   this.html =
    //     '<p>tupian </p><p>tupian</p><p><br></p><p><img src="https://img1.baidu.com/it/u=608404415,1639465523&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800" alt="tupian" data-href="https://img1.baidu.com/it/u=608404415,1639465523&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800" style=""/></p>'
    // }, 1500)
  },
  methods: {
    handleCreated(editor) {
      this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错
      //   设置工具栏详情
      this.toolbarConfig = {
        excludeKeys: ['insertVideo', 'uploadVideo', 'group-video', 'fullScreen']
      }
    },
    handleChange(content) {
      const toolbar = DomEditor.getToolbar(content)
      //   查看工具栏列表toolbar.getConfig().toolbarKeys
      this.$emit('change', this.html)
    },
    uploaadImg(file, insertFn) {
      this.$emit('uploadImg', file, insertFn)
    },
    uploaadVideo(file, insertFn) {
      this.$emit('uploadVideo', file, insertFn)
    }
  },
  beforeDestroy() {
    const editor = this.editor
    if (editor == null) return
    editor.destroy() // 销毁编辑器
  }
}
</script>
<style src="@wangeditor/editor/dist/css/style.css"></style>

父组件使用:

父组件是在el-form表中使用的

<template>
  <div class="project-container">
    <el-form ref="form" :model="ruleForm" label-position="left" class="form">
      <el-form-item label="复现步骤" prop="reproduceStep" label-width="100px">
        <RichText v-model="ruleForm.reproduceStep" :readOnlys="readOnlys" @change="richTextChangeData" @uploadImg="richTextUploadImg"></RichText>
      </el-form-item>
    </el-form>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
import RichText from '@/components/RichText/index.vue'

export default Vue.extend({
  name: 'Index',
  components: {
    RichText
  },
  data() {
    return {
      ruleForm: {
        reproduceStep: ''
      }
    }
  },
  mounted() {
    this.setFormData()
  },

  methods: {
    richTextChangeData(val: string) {
      // 获取最新的html数据
      // this.ruleForm.reproduceStep = val
    },
   // 上传图片可跑通的demo
    richTextUploadImg(file: any, insertFn: any) {
      // 插入图片,调接口返回图片url,通过插入conteng
      let imgUrl = 'https://img1.baidu.com/it/u=608404415,1639465523&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800'
      insertFn(imgUrl)
      // 设置只读
      this.readOnlys = true
    },
    // 真实项目使用的,供参考
 async richTextUploadImg(file: any, insertFn: any) {
      try {
        // 处理入参
        const pcode = '11'
        const formData = new FormData()
        formData.append('file', file)
        formData.append('filePathCode', pcode)

        const response = await API.File.uploadFile(formData)
        if (response && response.data) {
          this.uploadId = response.data.id
          // 上传接口返回的id,入参给下个接口,获取可直接访问的图片link
          const downloadImagePath = '/yh/download/downloadImage'
          const fileId =  this.uploadId
          let imgUrl = `${downloadImagePath}?fileId=${fileId}`;
          insertFn(imgUrl) // 页面插入图片
        }
        this.readOnlys = true
      } catch (error) {
        warn(error, true)
      }
    },
    setFormData() {
      this.ruleForm.reproduceStep =
        '<p>tupian </p><p>tupian</p><p><br></p><p><img src="https://img1.baidu.com/it/u=608404415,1639465523&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800" alt="tupian" data-href="https://img1.baidu.com/it/u=608404415,1639465523&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800" style=""/></p>'
    }
  }
})
</script>


  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您介绍一下使用Vue3封装WangEditor富文本组件的步骤。 首先,我们需要安装WangEditorVue3,可以通过以下命令进行安装: ```bash npm install wangeditor@latest npm install vue@next ``` 接着,我们可以在Vue3的组件中使用WangEditor。下面是一个简单的示例: ```vue <template> <div ref="editorElem"></div> </template> <script> import WangEditor from 'wangeditor' export default { mounted() { const editor = new WangEditor(this.$refs.editorElem) editor.create() } } </script> ``` 在上面的代码中,我们通过import导入了WangEditor,并在mounted钩子函数中创建了一个新的编辑实例。注意,我们需要在组件的模板中添加一个ref属性,用于引用编辑的DOM元素。 如果您需要进一步封装WangEditor组件,可以考虑将其封装为一个Vue组件,以便在其他地方重复使用。下面是一个简单的示例: ```vue <template> <div :id="editorId"></div> </template> <script> import WangEditor from 'wangeditor' export default { props: { value: String, placeholder: String, height: { type: String, default: '300px' } }, data() { return { editorId: `editor-${Math.random().toString(36).substr(2, 9)}`, editor: null } }, mounted() { this.editor = new WangEditor(`#${this.editorId}`) this.editor.config.height = this.height this.editor.config.placeholder = this.placeholder this.editor.config.onchange = this.handleChange this.editor.create() this.editor.txt.html(this.value) }, methods: { handleChange() { this.$emit('input', this.editor.txt.html()) } }, beforeUnmount() { this.editor.destroy() } } </script> ``` 在上面的代码中,我们定义了一个WangEditor组件,并通过props接收了一些参数,包括组件的初始值、占位符和高度等。在mounted钩子函数中,我们创建了一个新的编辑实例,并通过config属性设置了一些编辑的配置项,包括高度、占位符和内容变化时的回调函数等。我们还通过handleChange方法监听了编辑内容的变化,并通过$emit方法向父组件发送了一个input事件,以便在父组件中更新组件的绑定值。最后,我们在beforeUnmount钩子函数中销毁了编辑实例,以避免内存泄漏。 使用时,您可以像使用其他自定义组件一样,在Vue3的模板中引用WangEditor组件,并通过v-model指令绑定组件的值: ```vue <template> <div> <wangeditor v-model="content" placeholder="请输入内容" height="500px" /> <div>{{ content }}</div> </div> </template> <script> import WangEditor from '@/components/WangEditor.vue' export default { components: { WangEditor }, data() { return { content: '' } } } </script> ``` 在上面的代码中,我们通过import导入了WangEditor组件,并在模板中引用了该组件。我们还通过v-model指令绑定了组件的值,以便在父组件中获取和更新该值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值