使用vue编写的,没有任何依赖,可改写其它形式
轻量级编辑器只是在document.execCommand()方法做了包装,不兼容的浏览器器生成的标签是一致的,所以的富文本的选择要根据项目决定

实现了一点功能,写了个dome,加深对富文本原理的理解


template

<div class="page-editor"><div class="editor-wrapper"><div class="toolbar"><ul @click="menuHandle"><li v-for="(item,index) in menuList" :key="index" :data-index="index"><a href="javascript:;" :class="[{'ban-operate': item.isActive}]"><i :class="['iconfont',item.icon]"></i></a></li></ul></div><div class="body" contenteditable="true" ref="editor" v-focus="true"@keyup.enter="enterHandle"@keyup.delete="deleteHandle"></div></div>
</div>

js

 template: tpl,data() {return {newNode:null,lastRange:null,selection:window.getSelection(),isIE:window.navigator.userAgent.indexOf("MSIE")>=1,menuList:[{icon:"icon-zitibiaoti",detail:"标题",isActive:false},{icon:"icon-jiacu",detail:"加粗",isActive:false},{icon:"icon-xieti",detail:"倾斜",isActive:false},{icon:"icon-youxuliebiao",detail:"有序列表",isActive:false}]}},created(){},mounted(){this.initEditor();},methods:{initEditor(){this.$refs.editor.innerHTML = "<p><br/></p>"},enterHandle(){let range = this.getRange();let el = this.getNode(range.commonAncestorContainer);if(range.collapsed) {if (el.nodeName === "DIV") {let p = document.createElement("p");p.innerHTML="<br>";el.parentNode.replaceChild(p,el);};}},deleteHandle(){const that = this;if(!that.$refs.editor.innerHTML){that.$refs.editor.innerHTML = "<p><br/></p>"}},menuHandle(el){let target = this.getTarget(el,"LI"),index = this.dataSet(target,"index");switch (index) {case 0:this.menuList[index].isActive= !this.menuList[index].isActive;this.titleBtn(this.menuList[index].isActive);break;case 1:this.menuList[index].isActive= !this.menuList[index].isActive;this.blodBtn(this.menuList[index].isActive);break;case 2:this.menuList[index].isActive= !this.menuList[index].isActive;this.italicBtn(this.menuList[index].isActive);break;case 3:this.menuList[index].isActive= !this.menuList[index].isActive;this.olListBtn(this.menuList[index].isActive);break;}},titleBtn(isFouce) {console.log(isFouce);if(isFouce){let insertHtml = "<span style='font-size:28px;'></span>";this.addHtml(insertHtml);}else{this.clearForm();}},blodBtn(isFouce){if(isFouce) {let insertHtml = "<span style='font-weight:600;'></span>";this.addHtml(insertHtml);}else{this.clearForm();}},italicBtn(isFouce){if(isFouce) {let insertHtml = "<i></i>";this.addHtml(insertHtml);}else{this.clearForm();}},olListBtn(isFouce){if(isFouce) {let range = this.getRange();document.execCommand("insertOrderedList");if (range.collapsed) {let el = range.commonAncestorContainer;while (el.nodeName !== "P") {el = el.parentNode;};let replaceNode = el.firstChild.cloneNode(true);el.parentNode.replaceChild(replaceNode, el);}this.clearRange(range);}else{this.clearForm();}},clearForm(){let range = this.getRange();let pNode = range.endContainer.parentNode.parentNode;if(pNode){let str = pNode.innerHTML.replace(/\u200B/g,'');range.selectNode(pNode);      //创建范围的内容range.extractContents();let fNode = document.createDocumentFragment();let newNode = document.createElement(pNode.nodeName);if(pNode.attributes['style']){let styles = pNode.attributes['style'].value;newNode.style= styles;}fNode.appendChild(newNode);if(str.indexOf("<br>")>-1){str = str.replace(/\<br>/g,'');}newNode.innerHTML = str+'\u200B <br>';range.insertNode(fNode);};range.setEndAfter(range.endContainer.parentNode);range.collapse(true);},getHtml(){return this.$refs.editor.innerHTML;},setHtml(val){this.$refs.editor.innerHTML = val;},clearHtml(){this.$refs.editor.innerHTML="<p><br></p>";},getRange(){if(this.selection.rangeCount>0){return this.selection.getRangeAt(0);};},addHtml(html){let range = this.getRange();let fragment = range.createContextualFragment(html);let node = fragment.firstChild;range.insertNode(fragment);if(!node.firstChild){let text = document.createTextNode("\u200B");node.appendChild(text)};range.setStart(node.firstChild,1);range.setEnd(node.firstChild,1);range.collapse(true);this.clearRange(range);},clearRange(range){this.lastRange = range.cloneRange();range.detach();range = null;this.selection.removeAllRanges();this.selection.addRange(this.lastRange);},dataSet(el,name){let index;if(el){if (el.dataset) {index = parseInt(el.dataset[name]);} else {index = parseInt(el.getAttribute('data-'+name));}return parseInt(index);}},getTarget(el,targetName) {let target = el.target;while(target.nodeName!==targetName){target = target.parentNode;};el.stopPropagation();return target;},getNode(el){while(el.nodeType!==1){el = el.parentNode;};return el;}},directives: {focus: {inserted: function (el,binding) {if(binding.value){el.focus();}}}}

less

.page-editor{position: relative;border: 1px solid #c9d8db;margin: 15px;.editor-wrapper{position: relative;background: #fff;}.toolbar{border-bottom: 1px solid #eee;background: #fff;ul li{position: relative;display: inline-block;font-size: 0;}ul li a{display: inline-block;width: 46px;height: 40px;outline: 0;color: #333;font-size: 14px;line-height: 40px;vertical-align: middle;text-align: center;text-decoration: none;}ul li a i{font-size: 18px;}}.body{font-size: 16px;font-family: arial,sans-serif;line-height: 1.6;color: #333;outline: 0;word-wrap: break-word;padding: 22px 15px 40px;min-height: 300px;cursor: text;position: relative;z-index: 1;background: 0 0;}.body{ol{margin-left: 15px;}}.ban-operate{background-color: #909399;}}

原生JS编写简单的编辑器相关推荐

  1. 原生API编写简单富文本编辑器001

    原生API编写简单富文本编辑器001 系列文章快速阅读: 富文本编辑器开发系列-1-基础概念 富文本编辑器开发系列2-document.execCommand 的API 富文本编辑器开发系列3-sel ...

  2. 原生js编写的todos

    原生js编写的todos 如果有什么问题,可以直接问我 <!DOCTYPE html> <html><head><meta charset="UTF ...

  3. css画钟表_利用css+原生js制作简单的钟表

    利用css+原生js制作简单的钟表.效果如下所示 实现该效果,分三大块:html.javascript.css html部分html部分比较简单,定义一个clock的div,内部有原点.时分秒针.日期 ...

  4. 原生JS实现简单放大镜效果

    [前言] 本文介绍下原生JS实现简单图片放大镜效果 [主体] 时间问题,直接上源码 <!DOCTYPE html> <html> <head><meta ch ...

  5. 原生js编写小米购物车

    原生js编写小米购物车案例 思路 一.将数据渲染到下方ul中 1.遍历数据添加到li标签内 二.渲染购物车内容,将ul中li添加到购物车.添加点击事件 1.加入购物车内容1.判断购物车内需不需要添加此 ...

  6. 深圳java培训:使用原生JS重构简单的音乐播放器

    深圳java培训:使用原生JS重构简单的音乐播放器 上次,我们使用Jquery开发了一款简单的音乐播放器(如下图), 后来学生希望能够用原生的JS重构一次, 那么,下面就来看看如何使用原生的JS重构吧 ...

  7. 用p5.js编写简单的动态图形——波纹扩散

    用p5.js编写简单的动态图形--波纹扩散 第一次使用p5.js写程序,如有错误请指出,多多指教. 没有下载p5.js的小伙伴可以直接使用网页版的,简单注册一个账号之后就可以保存代码啦. 网站:htt ...

  8. js html颜色代码,原生js编写的浏览器安全色网页拾色器色盘 生成颜色代码

    原生js编写的浏览器安全色网页拾色器 by js.alixixi.com #abc-colorPicker .colorPick-close,#filter-colorPicker .colorPic ...

  9. 利用HTML+WEBSQL(sqlite)完成创建数据库,完成对数据的增删改查(使用原生JS编写)

    前端和数据 在日常编写一些页面的时候总希望能够把"用户生产"的数据保存下来到数据库中.今天学习了如何用WEBSQL(可以理解为浏览器自带的SQLite数据库)进行数据的保存以及在前 ...

最新文章

  1. 学术论文模式图、统计图绘制
  2. 什么数据库最适合数据分析师
  3. 谈谈对于企业级系统架构的理解(zz)
  4. 基于经验的SOA成功原则
  5. MySQL - Explain深度剖析
  6. 优麒麟 使用samba的windows打印机_优麒麟 19.10 将于本月结束生命周期
  7. 绝不因寂寞而爱上别人
  8. 为什么不能在scrollview中直接添加一个image,然后使animation.begin()??
  9. FastDFS下的storage服务启动卡住
  10. LeetCode 84. Largest Rectangle in Histogram
  11. 【JavaScript回顾】闭包
  12. 601. 体育馆的人流量
  13. 百度文库下载工具(所有源码)
  14. 信息学奥赛一本通——解题目录
  15. 基于连续小波变换和卷积神经网络的轴承故障诊断研究
  16. 电脑重装系统后Win11扬声器无插座信息如何解决?
  17. Hulu校招补录已开始,1年内工作经验也可投!
  18. 二维泊松方程数值解-五点差分法-共轭梯度法-python实现
  19. 流量统计html代码,CNZZ数据专家
  20. 数字IC开发软件介绍

热门文章

  1. 国内ce认证机构有哪些 国内十大CE认证机构排名 做ce认证的公司推荐
  2. 随机算法java实现(同生日问题以及扑克牌24数问题)
  3. WebGIS开发绘制地图标注
  4. ubuntu系统(七):工控机连接手机热点
  5. 微信语音技术原理_干货 | 2 分钟论文:语音生成表情包背后的技术原理
  6. Excel公式大全 excel自动求减 15个常用excel函数公式
  7. Web前端学习笔记01:Web标准_HTML_lang_字符集_HTML标签的语义化
  8. 老男孩python 2018最新_2018最新老男孩全栈python第3期视频教程 完整版 附源码与笔记 | 52download...
  9. 高一下学期计算机,高一下学期自我评价
  10. 天干地支(python)