系统搭建六 ---------------- wangEditor富文本编辑器的二次封装和使用

576 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,点击查看活动详情

官网直达:Vue3 官方示例

1. 安装wangEditor和Vue3组件

yarn add @wangeditor/editor
# 或者 npm install @wangeditor/editor --save

yarn add @wangeditor/editor-for-vue@next
# 或者 npm install @wangeditor/editor-for-vue@next --save

2. wangEditor组件封装

<template>
  <div style="border: 1px solid #ccc; width: 100%">
    <!-- 工具栏 -->
    <Toolbar
      v-if="showToolbar"
      :editor="editorRef"
      :defaultConfig="toolbarConfig"
      style="border-bottom: 1px solid #ccc"
      :mode="mode"
      class="toolBar"
    />
    <!-- 编辑器 -->
    <!-- line-height: normal 解决光标和placeholder对不齐 --!>
    <Editor
      :defaultConfig="editorConfig"
      v-model="defaultHtml"
      @onChange="handleChange"
      style="height: 500px; overflow-y: hidden; line-height: normal"
      class="editor"
      :mode="mode"
      @onCreated="handleCreated"
    />
  </div>
</template>

<script lang="ts" setup>
import { onBeforeUnmount, watchEffect, shallowRef, reactive, toRefs } from 'vue'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'

// API 引用
import { uploadFileImg, uploadFileVideo } from '@/api/system/file/index'
const props = defineProps({
  content: {
    type: [String],
    default: ''
  },
  readOnly: {
    type: Boolean,
    default: false
  },
  // 自定义提示信息
  placeHolder: {
    type: String,
    default: '请输入.....'
  },
  // 是否展示工具栏
  showToolbar: {
    type: Boolean,
    default: true
  }
})
const emit = defineEmits(['update:content'])

// 编辑器实例,必须用 shallowRef
const editorRef = shallowRef()

const state = reactive({
  toolbarConfig: {},
  editorConfig: {
    placeholder: props.placeHolder,
    readOnly: props.readOnly,
    MENU_CONF: {
      uploadImage: {
        // 自定义图片上传
        async customUpload(file: any, insertFn: any) {
          // console.log('上传图片', file)
          uploadFileImg(file).then((response: any) => {
            const url = response
            insertFn(url)
          })
        }
      }
      // uploadVideo: {
      //   // 自定义视频上传
      //   async customUpload(file: any, insertFn: any) {
      //     // console.log('上传图片', file)
      //     uploadFileVideo(file).then((response: any) => {
      //       const url = response
      //       insertFn(url)
      //     })
      //   }
      // }
    }
  },
  defaultHtml: props.content,
  mode: 'default'
})
let { toolbarConfig, editorConfig, defaultHtml, mode } = toRefs(state)
// console.log(props.content, 'props.content')
// console.log(defaultHtml, 'defaultHtml')

// 侦听传入的props,因为第一次进入或者刷新时 props.content的值为空,侦听其值的改变
watchEffect(() => {
  defaultHtml.value = props.content
  // console.log(props.content, 'watchEffect')
})
// 编辑器创建完毕时的回调函数。
const handleCreated = (editor: any) => {
  editorRef.value = editor // 记录 editor 实例,重要!
}
// 编辑器内容、选区变化时的回调函数。
// 内容改变通知父组件
function handleChange(editor: any) {
  emit('update:content', editor.getHtml())
}

// 组件销毁时,也及时销毁编辑器
onBeforeUnmount(() => {
  const editor = editorRef.value
  if (editor == null) return
  editor.destroy()
})
</script>

<style src="@wangeditor/editor/dist/css/style.css"></style>

3. 使用


<template>
  <div class="component">
  	<Editor v-model:content="form.content" />
  </div>
</template>
<script setup lang="ts">
	import Editor from "@/components/WangEditor/index.vue";
</script>

4. 自定义是否需要展示工具栏(showToolbar)自定义输入时多提示信息(placeHolder)

<template>
<Editor
          :showToolbar="false"
          :placeHolder="placeHolder"
          style="width: 900px; minwidth: 600px"
        />
</template>
<script setup lang="ts">
const placeHolder = `<span style="color:red">(请勿输入邮箱、电话、链接,请不要包含性别歧视)</span><span>请输入岗位职责</span><br/><span>岗位职责</span><br/><span>1.......</span><br/><span>2.......</span><br/>
职位要求</span><br/><span>1.......</span><br/><span>2.......</span><br/>
补充说明<br/>
工作时间、晋升说明、培训情况等
`
</script>

没有工具栏,自定义placeholder

没有工具栏,自定义placeholder.png

5. 注意

  1. editorRef 必须用 shallowRef
  2. 组件销毁时,要及时销毁编辑器
  3. v-model:content 也可以直接只用 v-model,这样的话在组件中封装时 props 接受的 content 就写为 modelValue, emits 传递的就为 'update:modelValue'
  4. 自己遇到的问题,就是初始化或者刷新时,富文本编辑器没有值,只有二次才会出现,打印的值也是第一次为空,所以需要 watch 传入的值,可以解决(原因:自己猜测是因为富文本编辑器和组件之间生命周期的一些问题导致的,目前还没弄懂)
  5. 因为自己需要上传图片到 oss 上,所以自定义了图片的上传,但要注意一点,传入的图片格式(通过new FormData() 来 异步上传一个二进制文件)。
import request from '@/utils/request'
// 图片上传地址
export const uploadFileImg = (file: any) => {
// 通过FormData将文件转成二进制数据
  const formData = new FormData()
  // 像 formData 里面添加 字段 image 值为 file
  // 并将文件转二进制
  formData.append('image', file) 
  // console.log(formData)
  return request({
    url: '上传地址',
    method: 'POST',
    data: formData,
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  })
}

6. 想得到一个FormData对象:

var formdata = new FormData();

方案1:创建一个空的FormData对象,然后再用append方法逐个添加键值对:
var formdata = new FormData();
formdata.append("name", "呵呵");
formdata.append("url", "http://www.baidu.com/");
方案2:取得form元素对象,将它作为参数传入FormData对象中!
var formobj =  document.getElementById("form");
var formdata = new FormData(formobj);
方案3:利用form元素对象的getFormData方法生成它!
var formobj =  document.getElementById("form");
var formdata = formobj.getFormData()

FormData 内置API方法

  • FormData.append
  • FormData.delete
  • FormData.get
  • FormData.getAll
  • FormData.has
  • FormData.set