1. 安装 WangEditor 
    npm install wangeditor@4.6.10
    
  2. 封装 wangEditor 组件
    <template>
      <div style="border: 1px solid #ccc;">
        <Toolbar
          style="border-bottom: 1px solid #ccc;"
          :editor="editorRef"
          :defaultConfig="toolbarConfig"
          :mode="mode"
        />
        <Editor
          style="height: 500px; overflow-y: hidden;"
          v-model="valueHtml"
          :defaultConfig="editorConfig"
          :mode="mode"
          @onCreated="handleCreated"
        />
      </div>
    </template>
    
    <script>
    import '@wangeditor/editor/dist/css/style.css' // 引入 css
    
    import axios from 'axios'
    import { message } from 'ant-design-vue'
    import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
    
    // VITE_APP_QINIU_TOKEN 是获取 七牛云token的接口
    // VITE_APP_QINIUDOAMIN=https://upload-z2.qiniup.com/
    const { VITE_APP_QINIU_TOKEN, VITE_APP_QINIUDOAMIN } = import.meta.env
    
    import { watch, onBeforeUnmount, ref, shallowRef, onMounted } from 'vue'
    
    export default {
      name: 'AmEditor',
      components: { Editor, Toolbar },
      props: {
        content: {
          type: String,
        },
      },
      emits: ['update:content'],
      setup(props, { emit }) {
        // 编辑器实例,必须用 shallowRef
        const editorRef = shallowRef()
    
        // 内容 HTML
        const valueHtml = ref(props.content)
    
        // 模拟 ajax 异步获取内容
        onMounted(() => {
          valueHtml.value = ''
        })
    
        // 上传数据
        watch(
          () => valueHtml.value,
          (val) => {
            emit('update:content', val)
          },
          {
            deep: true,
          },
        )
    
        // 工具栏配置
        const toolbarConfig = {
          toolbarKeys: [
            // 菜单 key
            'headerSelect',
            'bold', // 加粗
            'italic', // 斜体
            'through', // 删除线
            'underline', // 下划线
            'bulletedList', // 无序列表
            'numberedList', // 有序列表
            'color', // 文字色彩
            'insertLink', // 插入链接
            'fontSize', // 字体大小
            'lineHeight', // 行高
            'uploadImage', // 上传图片
            'delIndent', // 缩进
            'indent', // 增进
            'deleteImage', //删除图片
            'divider', // 分割线
            'insertTable', // 插入表格
            'justifyCenter', // 居中对齐
            'justifyJustify', // 两端对齐
            'justifyLeft', // 左对齐
            'justifyRight', // 右对齐
            'undo', // 撤销
            'redo', // 重做
            'clearStyle', // 革除格局
            'fullScreen', // 全屏
          ],
        }
    
        const editorConfig = {
          placeholder: '请输出内容...', // 配置默认提醒
          // readOnly: true,
          MENU_CONF: {
            // 配置上传服务器地址
            uploadImage: {
              // 小于该值就插入 base64 格局(而不上传),默认为 0
              base64LimitSize: 5 * 1024, // 5kb
              // 单个文件的最大体积限度,默认为 2M
              // maxFileSize: 1 * 1024 * 1024, // 1M
              // // 最多可上传几个文件,默认为 100
              // maxNumberOfFiles: 5,
              // 抉择文件时的类型限度,默认为 ['image/*'] 。如不想限度,则设置为 []
              allowedFileTypes: ['image/*'],
              // 自定义上传
              async customUpload(file, insertFn) {
                // 文件上传
                // const formData = new FormData()
                // formData.set('file', file)
    
                const result = await customUpload(file)
    
                // 插入到富文本编辑器中,主见这里的三个参数都是必填的,要不然控制台报错:typeError: Cannot read properties of undefined (reading 'replace')
                insertFn(result, result, result)
              },
            },
          },
        }
    
        // 组件销毁时,也及时销毁编辑器
        onBeforeUnmount(() => {
          const editor = editorRef.value
          if (editor == null) return
          editor.destroy()
        })
    
        const handleCreated = (editor) => {
          editorRef.value = editor // 记录 editor 实例,重要!
        }
    
        // 处理上传参数
        const paramsImg = (file) => {
          return new Promise((resolve, reject) => {
            let fileName = file.name
            let key = `aimei/img/${fileName}`
            let data = {
              data: {
                id: 8,
                key: key,
                secret: '这个密钥是公司运维给的',
              },
            }
            resolve(data)
          })
        }
    
        // 获取七牛云上传token
        const getQiniuToken = (data) => {
          return new Promise((resolve, _reject) => {
            axios.post(VITE_APP_QINIU_TOKEN, data).then((res) => {
              resolve(res)
            })
          })
        }
    
        // 上传图片获取在线链接
        const customUpload = (file) => {
          return new Promise((resolve, _reject) => {
            paramsImg(file)
              .then((data) => {
                getQiniuToken(data)
                  .then((res) => {
                    if (
                      res &&
                      res.data.result_code === 0 &&
                      res.data.result_msg.includes('OK')
                    ) {
                      let domain = res.data.data.token_info.domain
                      const formData = new FormData()
                      formData.append('file', file.file)
                      formData.append('key', res.data.data.key)
                      formData.append('token', res.data.data.token_info.token)
                      axios
                        .post(`${VITE_APP_QINIUDOAMIN}`, formData, {
                          headers: {
                            'Content-Type': 'multipart/form-data',
                          },
                        })
                        .then((response) => {
                          if (response.status == 200) {
                            const url = `${location.protocol}//${domain}/${response.data.key}` // 上传成功之后将上传的状态改为done
                            return resolve(url)
                          }
                        })
                        .catch((res) => {
                          return _reject(res)
                          message.error('上传失败')
                        })
                    }
                  })
                  .finally(() => {})
              })
              .catch((error) => console.log('error', error))
          })
        }
    
        return {
          editorRef,
          valueHtml,
          mode: 'simple', // 或 'simple'
          toolbarConfig,
          editorConfig,
          handleCreated,
        }
      },
    }
    </script>
    
    <style lang="scss" scoped></style>
    
  3. 使用的方法
    引入这个组件,例如 <edit v-model:content="你的变量" /> 就可以了
Logo

前往低代码交流专区

更多推荐