Vue2-editor富文本编辑器的使用与封装

我们在Vue项目开发中或多或少都会需要富文本编辑器的功能,Vue2-editor是一个基于Vue2,Quill的富文本编辑器,使用简单方便,下面就来介绍一下基本的使用方法以及如何封装为一个通用组件的方法。

一、安装

npm install vue2-editor
npm install vue2-editor

OR

yarn add vue2-editor

二、使用

<template>
  <div id="app">
    <vue-editor v-model="content"></vue-editor>
  </div>
</template>

<script>
import { VueEditor } from "vue2-editor";

export default {
  components: {
    VueEditor
  },

  data() {
    return {
      content: "<h1>Some initial content</h1>"
    };
  }
};
</script>

很简单,这样基本的功能就可以使用起来了。

三、图片上传

通常富文本编辑器中还需要图片上传的功能,Vue2-editor接受一个imageAdded的事件,我们可以定义一个方法来绑定这个事件,以达到图片上传并插入编辑器中效果。

<template>
  <div id="app">
    <vue-editor id="editor" useCustomImageHandler @imageAdded="handleImageAdded" v-model="htmlForEditor"> </vue-editor>
  </div>
</template>

<script>
import { VueEditor } from "vue2-editor";
import axios from "axios";
export default {
  components: {
    VueEditor
  },

  data() {
    return {
      htmlForEditor: ""
    };
  },

  methods: {
    handleImageAdded: function(file, Editor, cursorLocation, resetUploader) {
      var formData = new FormData();
      formData.append("image", file); // 定义字段名

      axios({
        url: "https://fakeapi.yoursite.com/images", // 文件上传URL
        method: "POST",
        data: formData
      })
        .then(result => {
          let url = result.data.data; // Get url from response
          Editor.insertEmbed(cursorLocation, "image", url);
          resetUploader();
        })
        .catch(err => {
          console.log(err);
        });
    }
  }
};
</script>

后端代码,我这里是PHP的,供参考:

<?php

namespace app\admin\controller;

use think\Controller;
use think\Request;

class File extends Controller
{
    protected $basePath;
    protected $dirPath;
    public function initialize()
    {
        $this->dirPath = '/uploads';
        $this->basePath = ROOT_PATH . $this->dirPath;
    }

    public function uploadImage()
    {
        $file = request()->file('image');
        $size = 2048000;
        $ext = 'jpg,png,gif'
        if (empty($file)) {
            exception('请选择需要上传的文件');
        }
        
        $path = $this->basePath;
        if (!file_exists($path)) {
            mkdir($path, 0777, true);
        }
        $info = $file->validate(['size' => $size, 'ext' => 'jpg,png,gif'])->move($path);
        if ($info) {
            // 成功上传后 获取上传信息
            return  '/uploads/' . $info->getSaveName();
        } else {
            // 上传失败获取错误信息
            exception($file->getError());
        }
    }
}

四、封装为通用组件

现在,基本的使用方法我们都会了,就会出现另一个问题,一个项目可能有多个页面会使用编辑器,如果每个页面都这样写一遍,就会造成资源和时间的浪费,也不符合可复用的组件化思想,先把代码贴上:

<template>
  <div class="editor">
    <vue-editor
      useCustomImageHandler
      @text-change="textChange"
      @imageAdded="handleImageAdded"
      v-model="editorContent"
    ></vue-editor>
  </div>
</template>
<script>
import axios from 'axios'
import { VueEditor, Quill } from 'vue2-editor'
export default {
  name: 'Editor',
  props: {
    value: {
      default: ''
    }
  },
  components: {
    VueEditor
  },
  data() {
    return {
      editorContent: ''
    }
  },
  created() {
    this.editorContent = this.value
  },
  methods: {
    textChange() {
      this.$emit('input', this.editorContent)
    },
    handleImageAdded: function(file, Editor, cursorLocation, resetUploader) {
      var formData = new FormData()
      formData.append('file', file)

      axios({
        url: 'file/upload',
        method: 'POST',
        headers: {
          Authorization: 'Bearer ' + this.$store.getters.token
        },
        data: formData
      })
        .then(result => {
          let url = result.data.data // Get url from response
          Editor.insertEmbed(cursorLocation, 'image', url)
          resetUploader()
        })
        .catch(err => {
          console.log(err)
        })
    }
  },
  watch: {
    value(newVal, oldVal) {
      this.editorContent = newVal
    }
  }
}
</script>
<style lang="sass" scoped>
.editor{line-height: normal;}
</style>
说明:

接收Props,当页面调用组件通过v-model传prop时,组件通过value获取值。

props: {
    value: {
      default: ''
    }
  }

当组件载入的时候通过created生命周期来初始化内容。

created() {
    this.editorContent = this.value
}

axios 添加header用于上传图片时后端获取并校验。

headers: {
          Authorization: 'Bearer ' + this.$store.getters.token
        }

监听editor内容变化,及时更新content

watch: {
    value(newVal, oldVal) {
      this.editorContent = newVal
    }
  }

textChange方法对应editor的@text-change事件,发生改变时要及时更新,通过this.$emit(‘input’, this.editorContent)把改变的content更新到页面绑定的变量

<vue-editor
      useCustomImageHandler
      @text-change="textChange"
      @imageAdded="handleImageAdded"
      v-model="editorContent"
    ></vue-editor>

textChange() {
    this.$emit('input', this.editorContent)
}

五、页面调用组件

<template>
  <div class="app-container">
   <editor v-model="content"></editor>
   <el-button type="primary" @click="save()">确 定</el-button>
  </div>
</template>
import Editor from '@/components/editor'
export default {
  name: 'pageNews',
  components: {Editor},
  data() {
    return {
        content: ''
    }
  },
  methods: {
     save() {
        console.log(this.content)
     }
  }
}

封装为一个组件,我们就可以很方便的调用了。

You may also like...

发表评论

电子邮件地址不会被公开。 必填项已用*标注