wangEditor是一个轻量级 web 富文本编辑器,配置方便,使用简单。
官方文档:https://www.wangeditor.com/
本文介绍vue如何使用wangEditor,进行这些操作(编辑富文本内容/显示内容/上传图片/删除图片)。后台数据库中保存的富文本就是html,顺便把图片的地址一并保存在里面。

安装

npm安装wangEditor: npm install wangEditor
单个Vue页面使用

<template>
    <div>
        <!--编辑区域-->
        <div ref="editor" v-html="textEditor"></div>
 
        <!--显示区域,一定要用样式-->
        <pre class="sd_pre_change_note" style="overflow-y: scroll;" v-html="textDescription"></pre>
    </div>
</template>
<script>
import wangEditor from 'wangeditor'   // 引入 wangEditor
 
export default {
    name: 'JustTest',
    data (){
        textEditor:'',
        textDescription:'',
        editor:null,                //wangEditor编辑器
        imgsrc: [],
    },
    created () {
        this.createEditor()
    }destroyed() {
      this.editor.destroy()
      this.editor = null
    },
    methods: {
      //创建富文本编辑器
      createEditor(){
        let that = this
        const editor = new wangEditor(this.$refs.editor)        //创建编辑器
        editor.config.height = 370                         // 设置编辑区域高度为 500px
        editor.config.excludeMenus = [                   // 配置菜单栏,设置不需要的菜单
            'todo',
            'video'
        ],
        editor.config.showLinkImg = false            //隐藏插入网络图片的功能
        
        //文本内容发生变换
        editor.config.onchange = (newHtml) => {
          this.onContentchange(newHtml)
 
          this.textDescription = newHtml
        }
        
        //上传文件
        editor.config.uploadImgServer = 'http://127.0.0.1:8000/backend/upload'
        editor.config.uploadImgMaxSize = 2 * 1024 * 1024 // 2M
        editor.config.uploadImgAccept = ['jpg', 'jpeg', 'png']
        editor.config.uploadImgMaxLength = 3 // 一次最多上传 3 个图片
        editor.config.uploadImgParams = {
            updir: 'detail',
        }
        editor.config.uploadFileName = 'image'
     
        editor.config.uploadImgHooks = {
          before: function(xhr) {          // 上传图片之前
              // 可阻止图片上传
              // return {
              //     prevent: true,
              //     msg: '需要提示给用户的错误信息'
              // }
          },
          success: function(xhr) {            // 图片上传并返回了结果,图片插入已成功
              console.log('success', xhr)
          },
          fail: function(xhr, editor, resData) {            // 图片上传并返回了结果,但图片插入时出错了
              this.$message({type: 'error', message: '插入图片失败!'})
              console.log('fail', resData)
          },
          error: function(xhr, editor, resData) {          // 上传图片出错,一般为 http 请求的错误
            this.$message({type: 'error', message: '上传图片失败!'})
            console.log('error', xhr, resData)
          },
          timeout: function(xhr) {          // 上传图片超时
            this.$message({type: 'error', message: '上传图片超时!'})
            console.log('timeout')
          },
          // 图片上传并返回了结果,想要自己把图片插入到编辑器中
          // 例如服务器端返回的不是 { errno: 0, data: [...] } 这种格式,可使用 customInsert
          customInsert: function(insertImgFn, result) {
              // result 即服务端返回的接口
              // insertImgFn 可把图片插入到编辑器,传入图片 src ,执行函数即可
              insertImgFn(result.data[0])
              that.imgsrc = that.getSrc(editor.txt.html())    //获取富文本中包含的所有图片地址
          }
        }
        
        editor.create()
        this.editor = editor
      },
      // html 即变化之后的内容, 删除图片
      onContentchange(html){
        if (this.imgsrc.length !== 0) {
          let nowimgs = this.getSrc(html)
          let merge = this.imgsrc.concat(nowimgs).filter(function (v, i, arr) {
            return arr.indexOf(v) === arr.lastIndexOf(v)
          })
 
          //后台请求,删除图片
          let params = {imgPaths:JSON.stringify(merge)}
          this.axios.post(`/auditInfo/deleteImg`,qs.stringify(params))
          .then(response =>{
            console.log(response.data);
          })
          .catch(function (error) {
            console.log(error);
          });
 
          this.imgsrc = nowimgs
        }
      },
      //得到html中的图片地址
      getSrc (html) {
        var imgReg = /<img.*?(?:>|\/>)/gi
        // 匹配src属性
        var srcReg = /src=[\\"]?([^\\"]*)[\\"]?/i
        var arr = html.match(imgReg)
        let imgs = []
        if (arr) {
          for (let i = 0; i < arr.length; i++) {
            var src = arr[i].match(srcReg)[1]
            imgs.push(src)
          }
        }
        return imgs
      },
    }
}
</script>
<style scoped lang="less">
 
/*wangEditor css*/
/deep/.sd_pre_change_note{
  table {
    border-top: 1px solid #ccc;
    border-left: 1px solid #ccc;
  }
  table td, table th {
    border-bottom: 1px solid #ccc;
    border-right: 1px solid #ccc;
    padding: 3px 5px;
  }
  table th {
    background-color: #f1f1f1;
    border-bottom: 2px solid #ccc;
    text-align: center;
  }
  /* blockquote 样式 */
  blockquote {
    display: block;
    border-left: 8px solid #d0e5f2;
    padding: 5px 10px;
    margin: 10px 0;
    line-height: 1.4;
    font-size: 100%;
    background-color: #f1f1f1;
  }
 
  /* code 样式 */
  code {
    display: inline-block;
    *display: inline;
    *zoom: 1;
    background-color: #f1f1f1;
    border-radius: 3px;
    padding: 3px 5px;
    margin: 0 3px;
  }
  pre code {
    display: inline-flex;
  }
 
  /* ul ol 样式 */
  ul, ol {
    margin: 10px 0 10px 20px;
  }
</style>

后台部分 urls.py

from django.conf.urls import url
from django.urls import path
from Apps.AuditList import auditList as auditListViews
 
urlpatterns = [
    ...
    path('auditInfo/deleteImg', auditListViews.deleteImg, name='deleteImg'),
    path('backend/upload', auditListViews.uploadImags, name='uploadImags'),
    url(r'^auditImg/(?P<path>.*)$', serve, {'document_root': os.path.join(BASE_DIR, "static/img/detail"),}),  #显示静态资源 图片
    ...
]

views.py

from django.http import JsonResponse, HttpResponse
import os
import re
import json
 
 
def deleteImg(request):
    if request.method == 'POST':
        response = {}
        try:
            imgPaths = json.loads(request.POST.get('imgPaths','[]'))
            for i in imgPaths:
                matchData = re.search(r'auditImg/(.*)', i)
                if matchData:
                    BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
                    file_path = BASE_DIR + '/static/img/detail/'+matchData.groups()[0]        #拼出server上保存的图片路径
                    os.remove(file_path)           
            response['msg'] = 'success'
            response['error_num'] = 0
 
        except Exception as e:
            print(traceback.format_exc(limit=1))
            response['msg'] = str(e)
            response['error_num'] = 1
 
        return JsonResponse(response)
 
 
#audit富文本 上传图片   图片保存在/static/img/detail/下
def uploadImags(request):
    if request.method == 'POST':
        resp = {'errno': 100, 'data': '请选择图片'}
        upfiles = request.FILES.getlist('image', None)
        updir = request.POST.get('updir', 'common')
 
        if(upfiles == None):
            return HttpResponse(json.dumps(resp), content_type="application/json")
        
        resUrls = []
        resIds = []
        for up in upfiles:
            upfileres = _upload(up, updir)
            resUrls.append(upfileres['url'])
            resIds.append(upfileres['id'])
 
        #前端使用的plopload上传,一次上传一张,多张分多次上传, 使用的wangeditor,是多张图片是一次上传的
        if updir == 'detail':
            resp = {'errno': 0, 'data': resUrls}
        else:
            resp = {'errno': 200, 'id': resIds[0], 'url': resUrls[0]}
 
 
        return HttpResponse(json.dumps(resp), content_type="application/json")
 
def _upload(upfile, updir):
    new_file_name = _hash_filename(upfile.name)
    res_save_path = _get_path(updir)
    save_path = res_save_path['save_path']
    local_save_path = res_save_path['local_save_path']
    local_save_file = local_save_path + new_file_name
    save_file = save_path + new_file_name
    url = 'http://127.0.0.1:8000/' + save_file.replace('static/img/'+updir,'auditImg')
   
    with open(local_save_file, 'wb') as f:
        for line in upfile.chunks(): 
            f.write(line)
        f.close()
    
    return {'id': 23, 'url': url}
 
def _hash_filename(filename):
    _, suffix = os.path.splitext(filename)
    return '%s%s' % (uuid.uuid4().hex, suffix)
 
def _get_path(updir):
    if(updir == ''):
        path = 'static/img/' + time.strftime("%Y%m%d", time.localtime()) + '/'
    else:
        path = 'static/img/' + updir + '/' + time.strftime("%Y%m%d", time.localtime()) + '/'
    # 本地储存路径
    local_save_path = path
    # 数据库存储路径
    save_path = os.path.join(path)
    isExists = os.path.exists(local_save_path)
    if not isExists:
        os.makedirs(local_save_path) 
    
    return {'save_path': save_path, 'local_save_path': local_save_path}

1.富文本插入表情,保存html到后台失败

要使用富文本的表情图,需要设置该字段的格式为utf8mb4

ALTER TABLE auditinfo MODIFY testDescription TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

SHOW FULL COLUMNS FROM auditinfo;

2.插入图片成功了,但是还是要实现删除图片的功能,防止服务器保存无用的信息,删除图片的功能,成功添加.
3.wangEditor图片上传
1.图片上传

 var E = window.wangEditor
 var editor = new E('#editorMenu','#editor')
 //开启debug模式
 editor.customConfig.debug = true;
 // 关闭粘贴内容中的样式
 editor.customConfig.pasteFilterStyle = false
 // 忽略粘贴内容中的图片
 editor.customConfig.pasteIgnoreImg = true
 // 使用 base64 保存图片
 //editor.customConfig.uploadImgShowBase64 = true
 // 上传图片到服务器
 editor.customConfig.uploadFileName = 'myFile'; //设置文件上传的参数名称
 editor.customConfig.uploadImgServer = 'upload'; //设置上传文件的服务器路径
 editor.customConfig.uploadImgMaxSize = 10 * 1024 * 1024; // 将图片大小限制为 3M
 editor.customConfig.uploadImgMaxLength = 5;
 editor.customConfig.uploadImgHooks = {
   
    success: function (xhr, editor, result) {
        // 图片上传并返回结果,图片插入成功之后触发
        // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,result 是服务器端返回的结果
    },
    fail: function (xhr, editor, result) {
        // 图片上传并返回结果,但图片插入错误时触发
        // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象,result 是服务器端返回的结果
    },
    error: function (xhr, editor) {
        // 图片上传出错时触发
        // xhr 是 XMLHttpRequst 对象,editor 是编辑器对象
    }
    
 }

后台代码

@Data
public class WangEditor {
	
	private Integer errno; //错误代码,0 表示没有错误。
	private String[] data; //已上传的图片路径
	
	
	public WangEditor(String[] data) {
		super();
		this.errno = 0;
		this.data = data;
	}	
}
@RequestMapping(value = "/upload",method=RequestMethod.POST)
	@ResponseBody
	public WangEditor uploadFile(
			@RequestParam("myFile") MultipartFile multipartFile,
			HttpServletRequest request) {
		try {
			// 获取项目路径
			String realPath = request.getSession().getServletContext()
					.getRealPath("");
			InputStream inputStream = multipartFile.getInputStream();
			
			String contextPath = request.getServletContext().getContextPath();
			
			// 服务器根目录的路径
			String path = realPath.replace(contextPath.substring(1),"");
			// 根目录下新建文件夹upload,存放上传图片
			String uploadPath = path + "upload";
			// 获取文件名称
			String filename = Calendar.getInstance().getTimeInMillis()+"image";
			// 将文件上传的服务器根目录下的upload文件夹
			File file = new File(uploadPath, filename);
			FileUtils.copyInputStreamToFile(inputStream, file);
			// 返回图片访问路径
			String url = request.getScheme() + "://" + request.getServerName()
					+ ":" + request.getServerPort() + "/upload/" + filename;
			String [] strs = {url}; 
			WangEditor we = new WangEditor(strs);
			return we;
		} catch (IOException e) {
			logger.error("上传文件失败", e);
		}
		return null;
 
	}

2.多图片上传

editor.customConfig.customUploadImg = function (files, insert) {
    var data= new FormData();
    for(var i=0;i<files.length;i++){
        data.append("files",files[i]);
    }
    $.ajax({
        url:basePath + 'uploadFile/wangEditUploadImag',
        type: "POST",
        data: data,
             
        success:function(da){
                    
             if(da.errno == 0){
                  for(var j=0;j<da.data.length;j++){
                       insert(da.data[j]);
                  }
              }else{
                  alert(da.msg);
                  return;
              }
         }
     });
}   
@RequestMapping(value = "/upload1",method=RequestMethod.POST)
	@ResponseBody
	public WangEditor uploadFile(
			@RequestParam("files") MultipartFile[] files,
			HttpServletRequest request) {
 
		try {
			List list = new ArrayList();
			
			for(MultipartFile multipartFile:files) {
				// 获取项目路径
				String realPath = request.getSession().getServletContext()
						.getRealPath("");
				InputStream inputStream = multipartFile.getInputStream();
				
				//String contextPath = request.getServletContext().getContextPath();
				//logger.info(contextPath);
				// 服务器根目录的路径
				String path = realPath;
				// 根目录下新建文件夹upload,存放上传图片
				String uploadPath = path + "upload";
				// 获取文件名称
				String filename = Calendar.getInstance().getTimeInMillis()+"image";
				// 将文件上传的服务器根目录下的upload文件夹
				File file = new File(uploadPath, filename);
				FileUtils.copyInputStreamToFile(inputStream, file);
				// 返回图片访问路径
				String url = request.getScheme() + "://" + request.getServerName()
						+ ":" + request.getServerPort() + "/upload/" + filename;
				list.add(url);
				
			}
			//ArrayList<String> list=new ArrayList<String>();
 
			String[] strings = new String[list.size()];
 
			list.toArray(strings);
			WangEditor we = new WangEditor(strings);
			return we;
		} catch (IOException e) {
			logger.error("上传文件失败", e);
		}
		return null;
 
	}

其他富文本编辑器:
TinyMCE:这是一个非常流行的富文本编辑器,广泛用于网页内容的编辑。它提供了丰富的插件和主题,可以高度定制以满足不同用户的需求。
CKEditor:另一个广泛使用的富文本编辑器,以其稳定性和强大的功能而闻名。CKEditor提供了所见即所得的编辑体验,并且支持各种文件格式的导入和导出。
UEditor:这是一个由百度团队开发的富文本编辑器,支持多种语言,具有丰富的功能和良好的兼容性。
MarkitUp:一个轻量级的、可定制的jQuery富文本编辑器,适用于CMS、博客、论坛等。
jwYSIWYG:一个简单的jQuery所见即所得编辑器,提供了基本的文字编辑和图片链接功能。
Lightweight RTE:一个非常轻量级的jQuery富文本编辑器,只提供基本的文字格式化功能。
HTMLBox:一个跨浏览器的开源jQuery富文本编辑器,具有很好的交互性和用户手册,便于集成。
AiEditor:一个面向AI的下一代富文本编辑器,支持全框架,并且对Markdown友好。
Textbus:一个以组件为中心,数据驱动的富文本编辑器开发框架,旨在解决传统富文本开发中遇到的问题。

GitHub 加速计划 / vu / vue
80
16
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:4 个月前 )
73486cb5 * chore: fix link broken Signed-off-by: snoppy <michaleli@foxmail.com> * Update packages/template-compiler/README.md [skip ci] --------- Signed-off-by: snoppy <michaleli@foxmail.com> Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 6 个月前
e428d891 Updated Browser Compatibility reference. The previous currently returns HTTP 404. 6 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐