基于wangEditor封装的 富文本组件

847 阅读3分钟

2022-蜘蛛侠-无路可归.jpg

前言

写公司的后台管理系统需要富文本编辑框 因为表格使用的是avue的框架,所以刚开始选择编辑器的时候是想用avue基于wangEditor封装的组件 avue-plugin-ueditor 但是由于过度封装的问题导致不适合我们公司上传照片的需求,我们是前端OSS直传的,需要在上传照片的时候把签名一起带过去验证 但是avue没办法带数据,且没办法自定义传输方法,无奈只能放弃,直接使用wangEditor,因为很多地方都会用到富文本编辑框,所以打算把它封装成一个组件 复用性比较强,比较方便

1.使用wangEditor

官网 www.wangeditor.com/v5/installa…

  1. 安装 editor 使用 npm install @wangeditor/editor --save
  2. 安装vue2所使用的组件 使用npm install @wangEditor/editor-for-vue --save
  • 因为我这里使用的技术栈是vue2 所以只展示vue2的用法

2.封装

  1. 在组件中引入wangEditor组件

import { Editor, Toolbar } from "@wangeditor/editor-for-vue";

  1. 在组件中使用它
<template slot="detailsForm">
<!-- // wangEditor富文本编辑器的封装组件 -->
  <div class="editWidth" 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;"
      v-model="html"
      :defaultConfig="editorConfig"
      :mode="mode"
      @onCreated="onCreated"
      @onChange="increase"
    />
  </div>
</template>

其中 toolbarConfig editorConfig 分别是富文本编辑器的工具栏配置和编辑配置 我这里工具栏使用的是默认配置,感兴趣或者有需求的同学可以去官网看

editorConfig: {
        placeholder: "请输入内容...",
        readOnly: false,
        MENU_CONF: {
          uploadImage: {
            server: "上传服务器的地址",
            customUpload: ""
          }
        }
      },

这里是我所使用的编辑配置 重点说一下配置自定义上传方法 想要配置自定义上传方法必须要在 editorConfig配置下的MENU_CONF菜单下的uploadImage的customUpload里面定义方法 不清楚的可以自行去看官网(这里是定义在data里面的还没有定义方法)

  1. 定义自定义上传方法
    this.editorConfig.readOnly = this.readOnly;
    this.editorConfig.MENU_CONF["uploadImage"] = {
      async customUpload(file, insertFn) {
        let imageUrl = await that.$uploadImage(file);
        insertFn(imageUrl);
      }
    };

我这里是定义在created生命周期里面的可以看到在里面我自定义了 customUpload上传方法 里面的 that.$uploadImage(file)是我自己按照公司需求封装的上传照片的方法,不是wangEditor自带的方法,你们可以写你们的上传方法 insertFn就是把图片插入编辑器里面的方法,这个是wangEditor自带的,直接使用,把后端返回的图片地址传入其中即可

有一点需要注意:就是 @onCreated="onCreated"方法时必须的,否则工具栏加载不出来

  // 工具栏初始化
    onCreated(editor) {
      this.editor = Object.seal(editor); // 一定要用 Object.seal() ,否则会报错
      console.log("我初始化了1", this.value);
      this.html = this.value;
    },

``

父子组件交互传值

既然是封装组件 那么就必须要和父组件有所交互,进行数据传输 主要就是实现父子组件使用v-model双向绑定数据 同步访问 有一下两种方式

第一种:利用 this.$emit("input","value");

首先 如果你在父组件中使用了v-model对子组件进行了值的绑定 比如

<wangEditor v-model="localValue" :readOnly="isreadOnly" />

我对wangEditor子组件进行了localValue的数据绑定 那么正常情况下在子组件中会默认将父组件中的v-model绑定的值 赋给子组件中名为value的props,但是你依然需要在子组件中的props定义value才行

    value: {
      type: String,
      default: 0
    },
    readOnly: {
      type: Boolean,
      default: false
    }
  },

这里我在props声明的value接受的就是localValue传过来的值,因为编辑框是在在子组件中的 所以要把值传给父组件 所以这里就需要到了 this.$emit("input","value"); 这里绑定的事件是 input 所以可以直接把value直接传给父组件的localValue里面 通过wangEditor组件的@onChange监听increase方法 进行传值

increase() {
      this.$emit("input", this.html);
    }

还有就是 我在这里总共是给子组件传了两个参数 一个是 localValue 还有一个是控制是否可编辑的readOnly参数,需要注意的一点是 就是正常情况下 有时候只会在第一次加载的时候给子组件传的值他才会生效,后面你在父组件里面通过事件去改变传的值会不生效 原因并不是没把值传过去,而是他把值传过去了 但是并没有执行赋值操作 (第一次赋值是在子组件生命周期里面赋值,你再次传值并没有执行生命周期 所以相当于传过去了,但数据没有更新) 所以需要使用watch监听数据 来实时更新子组件的状态

watch: {
    readOnly(newValue) {
      this.editorConfig.readOnly = newValue;
    },
    value(newValue){
        this.html= newValue
    }
  },

现在已经完成父子组件的双向绑定了,你在子元素中触发increase()函数或者在父组件中改变localValue变量,父子组件都会分别触发值的改变 配合watch就可以监听了

第二种方法 使用model进行绑定

我使用的是第一种方法 所以第二种方法仅仅是为了记录 下面是参考文档blog.csdn.net/qq_43061933…

可以去看vue的官网概念

允许一个自定义组件在使用 v-model 时定制 prop 和 event。默认情况下,一个组件上的 v-model 会把 value 用作prop 且把 input 用作 event,但是一些输入类型比如单选框和复选框按钮可能想使用 value prop 来达到不同的目的。使用 model 选项可以回避这些情况产生的冲突。

简单来说就是父组件改变值,子组件的值会改变,子组件改变值,父组件的值也会改变;就是将父子组件实现数据双向绑定的效果。

<template>
<div> <son v-model='formData.value'></son> <button @click="changeVal">点击变化value</button> </div>
</template>
watch :{ 
value (val) {
console.log( '父组件看见的' + val)
    } 
},

这里使用 v-model绑定了值 changeVal方法就是的单纯改变formData.value的值而已

子组件

<div> <input type="text" v-model="childValue" @input="childInputChange"/> </div>

子组件里面 使用model 定义一个prop和event prop就是props声明的参数 它就相当于第一种方法种的value 接受的是父组件v-model绑定的值 childValueChange事件就是input事件 需要在data里面关联childValue和fatherValue 然后绑定 childValue

export default {
  name: 'son',
  model: {  // 定义model
        	// 父组件v-model绑定的值传递给props中的fatherValue
            prop: 'fatherValue',  
            // 通过emit触发childValueChange将内部值传递给父组件v-model绑定的值
            event: 'childValueChange'  
        },
  props:{
      fatherValue:{ // 接受父组件传递的值
        type: String,
        default:''
      }  
    },
  data () {
    return {
      childValue: this.fatherValue// 关联值
    }
  },
  watch :{
    fatherValue (val) { //这一步重新赋值 是因为props里面的fatherValue改变了 但是data里面的childValue不会改变 从而视图不会更新
      console.log( '父组件看见的' + val)
      this.childValue = val
    }
  },
  methods:{
     childInputChange(){ 
        // 通过$emit触发childValueChange(model内定义)事件,将内部值传递给给父组件
        this.$emit('childValueChange', this.childValue)
    }
  },
}
</script>
————————————————
版权声明:本文为CSDN博主「平头的春天丶」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_43061933/article/details/125392777