近期由于需要对公司运营系统进行优化和升级,而原有后台系统所使用的vue-quill-editor编辑器对粘贴进来的内容的行内样式全部进行了过滤,虽然这样可以防止XSS攻击,但是却完全无法满足业务需要,为此对编辑器进行了更换,采用Vue-html5-editor 这个编辑器。

这是一个基于Vue 2.0系列的编辑器(官方地址),还不错,但却存在一些问题,以下记录这些问题,并提供解决办法。

1. 复制网络图片时无法粘贴成功

主要原因是图片链接存在跨域问题。运营人员复制的内容都是基于微信环境的,微信对所有的图片链接地址加了crossorigin="anonymous",所以复制图片的时候无法正常显示出来。

解决的办法是在编辑器的更新事件触发时,对所有的img图片链接中的crossorigin="anonymous"替换为空,代码如下:

// 更新编辑器内容
updateData(){let obj = document.getElementsByClassName("content")[0];let html = obj.innerHTML;let filterHtml =  html.replace(/crossorigin="anonymous"/g,"");this.content  = filterHtml;// 编辑器封装后,将内容传出去this.$emit('contentChange',filterHtml);
},

2. 无法从已有的图库中选择图片

此编辑器插入图片的方式主要有两种,一是输入链接插入图片,二是选择本地的图片转成base64后插入图片。

很显然,没法使用公司已经有素材库的图片,为此需要对该编辑器的源码做一些修改, 主要修改如下:

1. 将“上传”改为“选择”。修改文件 vue-html5-editor.js ,大约在310行的 template$3 变量中;

2. 将以前触发上传的事件改为触发一个打开选择图片的模态框,以便选择图库中的图片。修改文件vue-html5-editor.js ,大约在343行的pick事件中;

pick: function pick() {// 取消触发上传图片的事件// this.$refs.file.click();// 自定义的触发图片选择模态框的事件this.$parent.$parent.openModal();},

以下是图片选择的模态框展示:

3. 由于从图库中选择图片获取的仅仅是一个图片的链接地址,最终也是要以图片的形式插入编辑器中的,而编辑器插入图片的功能本身是比较OK的,为了省事,决定借用编辑器的插入图片功能,所以定义了一个事件,用于接收选择的图片地址,然后将图片的链接地址赋给编辑器自带的插入图片的输入链接框中,然后点击“确定”就可以插入图片了;

代码如下:

// 选择的图片地址
selectedImageUrl(url){let obj = this.$refs.editor.$children;// imageUrl为编辑器原有的变量obj[0].imageUrl = url;
},

3. 插入的图片没有做宽度限制

由于图库中有些图片的尺寸比较大,会超出编辑器的总宽度,导致排版比较难看,为此在插入新图片时,需要给图片加一个行内样式,即宽度为百分百。

设置图片宽度的代码如下:

// 设置图片宽度
setImageWidth(){this.$nextTick(()=>{let list = document.querySelectorAll(".vue-html5-editor .content img");if(list.length){for(let i=0;i<list.length;i++){let img = list[i];img.style.width = "100%";}};});
}

同时在编辑器插入图片的事件中调用上面这个方法,修改文件vue-html5-editor.js ,大约在 333 行的 insertImageUrl 事件中,代码如下:

insertImageUrl: function insertImageUrl() {if (!this.imageUrl) {return}this.$parent.execCommand(Command.INSERT_IMAGE, this.imageUrl);// 对新插入的图片设置图片最大宽度this.$parent.$parent.setImageWidth();this.imageUrl = null;
},

4. 给图片加超链接

由于在富文本里是有很多图片是要加超链接的,这个编辑器提供的加超链接是真心不好用,需要用鼠标选中文本或是图片才能加超链接,运营人员反映相当麻烦,而且加了链接也看不到是否加成功了的标识。

实现思路如下:

1. 在编辑器的内容更新时,给富文本中所有的图片加上一个data-index,并同时加上点击事件。当点击当前图片时,获取当前图片的HTML、自定义的data-index,同时获取当前图片的父元素,如果当前图片的父元素是已经加了链接的A标签,则获取A标签的链接地址以方便修改;

// 给图片添加事件
addImgEvent(){let imgs = document.querySelectorAll(".vue-html5-editor img");for(let i=0;i<imgs.length;i++){let img = imgs[i];img.style.cursor="pointer";img.setAttribute("data-index",i);img.onclick = (e)=>{// 显示加链接的对话框this.showImgLinkModal = true;// 区取当前图片的HTMLthis.imgTarget = e.target.outerHTML;// 获取当前图片自定义的indexthis.imgIndex = e.target.getAttribute("data-index");// 获取当前元素的父元素let parent = e.target.parentElement;// 如果图片的父元素是已经加了链接的A标签if(parent.tagName=='A'){// 获取A标签的链接地址,方便修改链接地址this.imgLink = parent.getAttribute("href");}}}
},

2. 确认添加图片链接时,根据当前图片是否已经添加了链接来做不同的处理。如果没有加链接就加上;如果已经加了链接,就更新链接地址;

// HTML转换为DOM结点
parseElement(htmlString){return new DOMParser().parseFromString(htmlString,'text/html').body.childNodes[0];
},// 确认添加图片链接
confirmAddLink(){// 加了链接的标识符let span = '<span id="linkMark" style="width: 26px;height: 26px;display: block;position: absolute;top: 5px;right: 5px;background: url(data:image/png;base64,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) no-repeat center;background-size: contain; "></span>';// 当前图片let img = this.imgTarget;// 图片添加链接后的HTMLlet a = '<a style="position:relative;display:block" href="'+this.imgLink+'">'+span+img+'</a>';// 将HTML转换为节点类型let spanNode = this.parseElement(span);let aNode = this.parseElement(a);// 获取当前图片let index = this.imgIndex;let imgs = document.querySelectorAll(".vue-html5-editor img");let current = imgs[index];let children = current.parentNode.children;// 如果当前图片父元素不是A标签if(current.parentNode.tagName!='A'){for(let i=0;i<children.length;i++){let item = children[i];// 如果子节点中的某一个节点等于当前图片对象if(item.isEqualNode(current)){// 将加了链接的图片添加到当前节点下一个节点之前current.parentNode.insertBefore(aNode, item.nextSibling);// 移除没有加链接的图片current.parentNode.removeChild(item);break;}};}else{let link = this.imgLink;// 重新给当前图片的父元素A标签设置可能更改的链接current.parentNode.setAttribute("href",link);// 给富文本中的图片本身存在链接设置样式,防置链接是原有的current.parentNode.setAttribute("style","position:relative;display:block");let hasLinkMark=false;// 判断是否有链接标识for(let i=0;i<children.length;i++){let item = children[i];if(item!=current ){if(item.tagName=='SPAN' && item.id=="linkMark"){hasLinkMark=true;}else{current.parentNode.removeChild(item); }}};// 如果没有链接标识if(!hasLinkMark){// 添加一个链接标识current.parentNode.insertBefore(spanNode,children[0]);}};// 关闭添加链接的模态框this.closeImgLinkModal();// 更新图片事件this.addImgEvent();this.$nextTick(()=>{let result = document.querySelectorAll(".content")[0].innerHTML;this.data.content = result;});},

3. 关闭图片添加链接的模态框;

// 关闭插入图片链接模态框
closeImgLinkModal(){this.showImgLinkModal = false;this.imgTarget = null;this.imgIndex = null;this.imgLink = "";
},

以下是加了链接的效果:

5. 代码实现

以下是封装好的编辑器文件代码。

<template><div><vue-html5-editor ref="editor":height="960" :content="content" :auto-height="false"  @change="updateData"></vue-html5-editor></div>
</template><script>
// npm install font-awesome --save
import "font-awesome/css/font-awesome.css" export default {name:"editor",props: {// 打开图片选择框openModal:{type:Function}},data() {return {content:"",}},mounted(){},methods: {// 更新编辑器内容updateData(){let obj = document.getElementsByClassName("content")[0];let html = obj.innerHTML;let filterHtml =  html.replace(/crossorigin="anonymous"/g,"");this.content  = filterHtml;// 编辑器封装后,将内容传出去this.$emit('contentChange',filterHtml);},// 选择的图片地址selectedImageUrl(url){let obj = this.$refs.editor.$children;// imageUrl为编辑器原有的变量obj[0].imageUrl = url;},// 设置图片宽度setImageWidth(){this.$nextTick(()=>{let list = document.querySelectorAll(".vue-html5-editor .content img");if(list.length){for(let i=0;i<list.length;i++){let img = list[i];img.style.width = "100%";}};});}},
}
</script>

以下是调用编辑器的文件代码,相关无用代码已经做了清除,可根据需要自行添加。

<template><div><!-- 调用编辑器 --><div class="editor-box"><my-editor ref="myEditor" @contentChange="contentChange" :openModal="openModal"></my-editor></div><!-- 图片素材库--><el-dialog title="选择图片" :visible.sync="showSelectImgModal" @close="closeModal" width="960px"><div class="img-modal"><div class="image-list"><el-uploadname="img"class="avatar-uploader"style="width:100px;height:100px;":multiple="false":headers="headers":action="uploadUrl":data="uploadData":show-file-list="false":on-success="onUploadSuccess":before-upload="onUploadBefore"accept=".jpg,.jpeg,.png,.gif,.bmp,.JPG,.JPEG,.PBG,.GIF,.BMP"><i class="el-icon-plus avatar-uploader-icon"></i></el-upload><div class="image-item" v-for="item in imageList" :key="item.id" @click="selectImage(item.path)"><el-image  fit="cover" :src="item.path"></el-image></div></div></div> </el-dialog><!-- 插入链接--><el-dialog title="插入链接" :visible.sync="showImgLinkModal" @close="closeImgLinkModal" width="800px"><div style="display:flex;"><el-input placeholder="请输入图片链接地址" v-model="imgLink"></el-input><el-button type="primary" style="margin-left:10px;" @click="confirmAddLink">确定</el-button></div></el-dialog></div></template><script>
// 引入封装后的编辑器组件
import editor from './components/editor';
// 引入获取Token的方法
import { getToken } from '@/utils/auth';export default {name: "myEditor",components:{'myEditor':editor},data() {return {// 编辑器的内容content:"",// 打开显示图库showSelectImgModal:false,// 图库图片列表imageList:[],// 上传图片地址(模拟)uploadUrl:"http://www.upload.com",// 上传图片验证headers: {authorization: getToken()},// 上传附加参数uploadData:{},// 添加链接showImgLinkModal:false,// 当前图片imgTarget:null,// 图片下标imgIndex:null,// 图片链接imgLink:"",};},created(){// 获取图片素材库this.getImage();},mounted(){},methods: {// 内容更新时contentChange(result){this.content = result;this.$nextTick(()=>{// 内容更新时给图片加事件this.addImgEvent();});},// 打开选择图片openModal(){this.showSelectImgModal = true;},// 获取微信图片getImage(){// 获取图库的接口中地址(模拟)let url = "getWechatImage";this.$http.get(url).then((result) => {if (result.code == 10000) {this.imageList = result.data;}});},// 上传以前onUploadBefore(file){const size = file.size / 1024 / 1024;if (size>10){this.$message.error('图片大小不能超过10MB');return false}},// 上传成功后onUploadSuccess(res){if(res.code==10000){// 重新获取图片库的图片this.getImage();}},// 选择图库图片selectImage(url){this.$refs.myEditor.selectedImageUrl(url);this.closeModal();},// 关闭选择图片closeModal(){this.showSelectImgModal = false;},// 给图片添加事件addImgEvent(){let imgs = document.querySelectorAll(".vue-html5-editor img");for(let i=0;i<imgs.length;i++){let img = imgs[i];img.style.cursor="pointer";img.setAttribute("data-index",i);img.onclick = (e)=>{// 显示加链接的对话框this.showImgLinkModal = true;// 区取当前图片的HTMLthis.imgTarget = e.target.outerHTML;// 获取当前图片自定义的indexthis.imgIndex = e.target.getAttribute("data-index");// 获取当前元素的父元素let parent = e.target.parentElement;// 如果图片的父元素是已经加了链接的A标签if(parent.tagName=='A'){// 获取A标签的链接地址,方便修改链接地址this.imgLink = parent.getAttribute("href");}}}},// 关闭插入图片链接模态框closeImgLinkModal(){this.showImgLinkModal = false;this.imgTarget = null;this.imgIndex = null;this.imgLink = "";},// HTML转换为DOM结点parseElement(htmlString){return new DOMParser().parseFromString(htmlString,'text/html').body.childNodes[0];},// 确认添加图片链接confirmAddLink(){// 加了链接的标识符let span = '<span id="linkMark" style="width: 26px;height: 26px;display: block;position: absolute;top: 5px;right: 5px;background: url(data:image/png;base64,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) no-repeat center;background-size: contain; "></span>';// 当前图片let img = this.imgTarget;// 图片添加链接后的HTMLlet a = '<a style="position:relative;display:block" href="'+this.imgLink+'">'+span+img+'</a>';// 将HTML转换为节点类型let spanNode = this.parseElement(span);let aNode = this.parseElement(a);// 获取当前图片let index = this.imgIndex;let imgs = document.querySelectorAll(".vue-html5-editor img");let current = imgs[index];let children = current.parentNode.children;// 如果当前图片父元素不是A标签if(current.parentNode.tagName!='A'){for(let i=0;i<children.length;i++){let item = children[i];// 如果子节点中的某一个节点等于当前图片对象if(item.isEqualNode(current)){// 将加了链接的图片添加到当前节点下一个节点之前current.parentNode.insertBefore(aNode, item.nextSibling);// 移除没有加链接的图片current.parentNode.removeChild(item);break;}};}else{let link = this.imgLink;// 重新给当前图片的父元素A标签设置可能更改的链接current.parentNode.setAttribute("href",link);// 给富文本中的图片本身存在链接设置样式,防置链接是原有的current.parentNode.setAttribute("style","position:relative;display:block");let hasLinkMark=false;// 判断是否有链接标识for(let i=0;i<children.length;i++){let item = children[i];if(item!=current ){if(item.tagName=='SPAN' && item.id=="linkMark"){hasLinkMark=true;}else{current.parentNode.removeChild(item); }}};// 如果没有链接标识if(!hasLinkMark){// 添加一个链接标识current.parentNode.insertBefore(spanNode,children[0]);}};// 关闭添加链接的模态框this.closeImgLinkModal();// 更新图片事件this.addImgEvent();this.$nextTick(()=>{let result = document.querySelectorAll(".content")[0].innerHTML;this.data.content = result;});}},
};
</script><style lang="scss" scoped>.editor-box{width:718px;height:1000px;overflow:hidden;
}.img-modal{width:100%;height:600px;overflow-y: auto;.image-list{width:100%;display: flex;flex-direction: row;justify-content: flex-start;flex-wrap: wrap;align-items: flex-start;.image-item{height:100px;width:100px;overflow: hidden;display: flex;flex-direction:column;justify-content:space-around;align-items:center;.el-image{width:100%;height:100%;cursor: pointer;}}}
}</style>

以下是上面代码中获取Token的文件代码:

// npm inatall js-cookie --save
import Cookies from 'js-cookie'const TokenKey = 'Admin-Token'export function getToken() {return Cookies.get(TokenKey)
}export function setToken(token) {return Cookies.set(TokenKey, token)
}export function removeToken() {return Cookies.remove(TokenKey)
}

如果上面的文件作为编辑素材时,可以用下面的代码对编辑器进行初始赋值。

this.$refs.myEditor.content = "要赋值的富文本";
// 设置内容中图片的宽度
this.$refs.myEditor.setImageWidth();

最后是在main.js中集成编辑器的代码。

// npm install vue-html5-editor --save
import VueHtml5Editor from 'vue-html5-editor'
var options = {// 全局组件名称,使用new VueHtml5Editor(options)时该选项无效 name: "vue-html5-editor",// 是否显示模块名称,开启的话会在工具栏的图标后台直接显示名称showModuleName: false,// 自定义各个图标的class,默认使用的是font-awesome提供的图标icons: {text: "fa fa-pencil",color: "fa fa-paint-brush",font: "fa fa-font",align: "fa fa-align-justify",list: "fa fa-list",link: "fa fa-chain",unlink: "fa fa-chain-broken",tabulation: "fa fa-table",image: "fa fa-file-image-o",hr: "fa fa-minus",eraser: "fa fa-eraser",undo: "fa-undo fa",info: "fa fa-info",},// 配置图片模块image: {// 文件最大体积,单位字节  max file sizesizeLimit: 512 * 1024,// 上传参数,默认把图片转为base64而不上传upload: {url: null,headers: {},params: {},fieldName: {}},// 压缩参数,默认使用localResizeIMG进行压缩,设置为null禁止压缩compress: {width: 1600,height: 1600,quality: 80},// 响应数据处理,最终返回图片链接uploadHandler(responseText){var json = JSON.parse(responseText)if (!json.ok) {alert(json.msg)} else {return json.data}}},// 语言,内建的有英文(en-us)和中文(zh-cn)language: "zh-cn",// 自定义语言i18n: {"zh-cn": {"align": "对齐方式","image": "图片","list": "列表","link": "链接","unlink": "去除链接","table": "表格","font": "文字","text": "排版","eraser": "格式清除","info": "关于","color": "颜色","please enter a url": "请输入地址","create link": "创建链接","bold": "加粗","italic": "倾斜","underline": "下划线","strike through": "删除线","subscript": "上标","superscript": "下标","heading": "标题","font name": "字体","font size": "文字大小","left justify": "左对齐","center justify": "居中","right justify": "右对齐","ordered list": "有序列表","unordered list": "无序列表","fore color": "前景色","background color": "背景色","row count": "行数","column count": "列数","save": "确定","upload": "上传","progress": "进度","unknown": "未知","please wait": "请稍等","error": "错误","abort": "中断","reset": "重置"}},// 隐藏不想要显示出来的模块hiddenModules: [],// 自定义要显示的模块,并控制顺序visibleModules: ["text","color","font","align","list","link","unlink","tabulation","image","hr","eraser","undo",],// 扩展模块,具体可以参考examples或查看源码modules: {}
};Vue.use(VueHtml5Editor,options);

Vue-html5-editor 编辑器的使用及一些问题解决相关推荐

  1. Vue引入 mavon-editor 编辑器的详细步骤

    Vue引入 mavon-editor 编辑器的详细步骤 一.编辑器的引入 如果你的项目之前没有安装过该编辑器,那就得先安装编辑器 在自己的项目的根目录执行下列命令: npm install mavon ...

  2. 推荐8款不错的HTML5文本编辑器

    如果你是一名Web开发人员,当你需要开发一个独特的网站时,你就会知道文本编辑器的重要性.小编为大家整理了8款非常前沿的HTML5文本编辑器,简化开发流程,喜欢就转走吧! Mercury Editor ...

  3. # Vue 中 JSON 编辑器使用

    Vue 中 JSON 编辑器使用 文章目录 Vue 中 JSON 编辑器使用 背景描述 vue-json-edit 安装依赖 测试页面 效果图 bin-code-editor 安装依赖 测试页面 效果 ...

  4. html中的ui编辑器,kendoUI系列教程之Editor编辑器

    kendoui的编辑器是我见过配置最复杂的,方法API一大堆. Configuration配置项 1.编码 encoded 类型:Boolean 默认:true 说明:配置编辑器提交时是否对内容编码, ...

  5. HTML5在线编辑器Wysihtml5之Bootstrap扩展

    为什么80%的码农都做不了架构师?>>>    HTML5在线编辑器Wysihtml5之Bootstrap扩展 bootstrap扩展后的效果 Wysihtml5在线编辑器 boot ...

  6. Unity3D Editor 编辑器扩展3 Editor脚本

    Unity3D Editor 编辑器扩展3 Editor脚本 环境:Unity2017.2 语言:C# 总起: 在编辑Unity项目的时候,总不可能避免的接触到Unity自身自带的Inspector参 ...

  7. CP Editor 编辑器(为竞赛而生的编辑器)的安装与配置

    CP Editor 编辑器(为竞赛而生的编辑器)的安装与配置 1. CP Editor 编辑器的下载 2. 配置环境变量 3. 配置个人化的 CP Editor 4. 配置完成测试 1. CP Edi ...

  8. uniapp的editor编辑器

    九.uniapp的editor编辑器 ​    editor 1.调用初始化的方法,目的是创建editor组件对应的 editorContext (实例上下文) @ready="onEdit ...

  9. html5在哪编辑器,HTML5文本编辑器推荐-属于Web开发人员的HTML5编辑器

    HTML5文本编辑器推荐-属于Web开发人员的HTML5编辑器 Web开发人员和设计人员经常需要用到HTML5文本编辑器,同时它也是Web开发人员最为重要的工具之一.由于HTML5技术的不断发展,为此 ...

  10. Vue 富文本编辑器插件 vue-quill-editor 坑!

    Vue3 + vue-quill-editor 安装步骤: vue3 安装vue-quill-editor npm install @vueup/vue-quill vue2 安装vue-quill- ...

最新文章

  1. WaveSwipeRefreshLayout
  2. 200万年薪,招不到清华姚班毕业生,能上姚班的都是什么人?
  3. 并发用户数和TPS的关系
  4. PD生成SQL脚本附带注释命令
  5. Linux 实操 —— 日志筛选操作(sed与wc命令介绍)
  6. 微信小程序webview内页面分享
  7. iClock时间菜单功能设置
  8. python可不可以同时执行1000个线程_python怎么能同时执行代码(多线程)?
  9. 华为端口聚合命令_华为汇聚交换机链路聚合配置命令
  10. Struts2 验证码图片实例
  11. php代码给用户安装浏览器,PHP判断用户浏览器是否安装alexa工具条程序
  12. 2022年Java面试题---中科创达
  13. Fuzz:插桩技术入门
  14. LUP分解求解线性方程组及求逆矩阵 java
  15. 双非计算机硕士在郑州,双非院校的研究生有必要读吗?答案非常现实!
  16. c语言程序设计题目湖南大学,湖南大学C语言期末考试样卷
  17. 数据分析、数据挖掘、机器学习实习面经总结
  18. Redis(6)——GeoHash查找附近的人
  19. 艾瑞发布《2021 年全球互联网通信云行业研究报告》,融云持续领跑市场
  20. 微信、支付宝先后发布声明!

热门文章

  1. pytorch和python的区别_Keras和PyTorch的视觉识别与迁移学习对比
  2. 网吧服务器最新方案,云更新2017版对网吧服务器配置要求
  3. Digital Booklet - Taylor Swift Karao-pdf
  4. C++学习(一八一)android的NDK、SDK版本的对应关系
  5. (基础)SpringCloud Alibaba Nacos作为多环境配置中心
  6. Forth 内存布局
  7. 压缩包修改所属目录Linux,linux文件/目录/压缩解压 操作指令
  8. 数据挖掘day04-微积分的本质10~11
  9. pc端MNIST数据集pytorch模型CNN网络转换为onnx部署树莓派4B和神经棒NCS2(使用openvino2021框架)
  10. html中如何使用正方形符号,正方形符号如何用MathType编辑