使用contenteditable="true"改造div可编辑文本框,并去除粘贴复制的格式问题

contenteditable=“true” 可编辑
contenteditable=“false” 禁止编辑
contenteditable=“plaintext-only” 可以让编辑区域只能键入纯文本 不建议使用兼容性不好

一:简单版

<template><div :contenteditable="contenteditable" class="contentAble" :placeholder="placeholder" @focus="isLocked = true" @blur="isLocked = false" @input="changeDivText($event)" @paste="optimizePasteEvent" v-html="content" />
</template><script>
export default {props: {placeholder: {type: String,default: '请输入内容'},value: {type: String,default: ''},contenteditable: {type: String,default: 'true'}},data() {return {content: this.value,isLocked: false}},watch: {'value'() {if (!this.isLocked || !this.content) {this.content = this.value}}},methods: {// 监听粘贴内容到输入框事件,对内容进行处理optimizePasteEvent(e) {e.stopPropagation()e.preventDefault()let text = ''; const event = (e.originalEvent || e)if (event.clipboardData && event.clipboardData.getData) {text = event.clipboardData.getData('text/plain')} else if (window.clipboardData && window.clipboardData.getData) {text = window.clipboardData.getData('text')}if (document.queryCommandSupported('insertText')) {document.execCommand('insertText', false, text)} else {document.execCommand('paste', false, text)}},// 获取内容changeDivText(e) {this.$emit('input', e.target.innerHTML)}}
}
</script><style lang="scss" scoped>
.contentAble{border-radius: 10px;border: 1px solid #dcdfe6;padding: 20px;min-height: 200px;&:empty::before {content: attr(placeholder);color: #c0c4cf;}
}
</style>

使用例子

import CanableText from '@/components/CanableText'
<CanableText v-model="content" placeholder="请输入内容" />

二:升级版(可插入图片或者粘贴图片)

<template><div><divref="editor":contenteditable="contenteditable"class="contentAble":class="{uploadImage:uploadImage}":placeholder="placeholder"@focus="isLocked = true"@blur="isLocked = false"@input="changeDivText($event)"@paste.prevent="handlePaste"v-html="content"/>//插入图片封装组件,代码太长,根据自己需求编写旧不展示了<EditorImage v-if="uploadImage" ref="EditorImage" @successCBK="imageSuccessCBK"><template v-slot:button><el-button class="blueBorBtn insetImg" @click="insertImg">插入图片</el-button></template></EditorImage></div>
</template><script>
import EditorImage from '@/components/Tinymce/components/EditorImage'
export default {components: { EditorImage },props: {placeholder: {type: String,default: '请输入内容'},value: {type: String,default: ''},contenteditable: {type: Boolean,default: true},imgShowWidth: { // 聊天输入框中粘贴的图片显示的宽度type: Number,default: 60},imgShowHeight: { // 聊天输入框中粘贴的图片显示的高度type: Number,default: 60},uploadImage: {type: Boolean,default: false}},data() {return {content: this.value,isLocked: false}},watch: {'value'() {if (!this.isLocked || !this.content) {this.content = this.value}}},methods: {async handlePaste(event) {const pasteResult = this.optimizePasteEvent(event)if (pasteResult) returnawait this.handlePasteImageFile(event.clipboardData)},// 监听粘贴文本到输入框事件,对内容进行处理optimizePasteEvent(e) {e.stopPropagation()e.preventDefault()let text = ''; const event = (e.originalEvent || e)if (event.clipboardData && event.clipboardData.getData) {text = event.clipboardData.getData('text/plain')} else if (window.clipboardData && window.clipboardData.getData) {text = window.clipboardData.getData('text')}if (document.queryCommandSupported('insertText')) {document.execCommand('insertText', false, text)} else {document.execCommand('paste', false, text)}if (text) return truereturn false},// 粘贴图片(可以粘贴图片路径显示图片在文本框中)async handlePasteImageFile(clipboardData) {const img = this.getPasteImageFile(clipboardData.files)if (!img) return//这段代码为上次图片接口结果得到的路径,根据自己需求编写//this.uploadFileList = [{//  raw: img,//  size: img.size,//  name: img.name,//  chunkList: [],//  status: this.FileStatus.wait,//  progressStatus: 'warning',//  uploadProgress: 0//}]//this.uploadFileList.length && this.submitUpload(async result => {//  if (!result) {//    return this.$message.error('图片上传失败,请重新上传')//  }const oImage = await this.getImageObject(result, this.imgShowWidth, this.imgShowHeight)this.cursorInsert(oImage)this.changeDivText()// })},getPasteImageFile(clipboardDataFiles) {if (!clipboardDataFiles.length) {// console.log('没有要粘贴的文件')return null}// 剪切版中选择的(用户第一个点的在尾)第一张图片const clipboardDataFileList = Array.from(clipboardDataFiles || [])let firstSelectedImage = nullclipboardDataFileList.forEach(file => {if (!file.type.match(/image\//i)) {return}firstSelectedImage = file})/*** 这里的 firstSelectedFile 对象就是和 <input type="file" /> onchange 时 一样的 文件对象* */return firstSelectedImage},// 获取一个 image objectgetImageObject(uploadRes, showWidth, showHeight) {const oImage = new Image(showWidth, showHeight)oImage.src = uploadRes.urlreturn oImage},// 光标处插入节点cursorInsert(node) {// 获取光标范围if (window.getSelection()) {this.focus()}const selObj = window.getSelection()const range = selObj.getRangeAt(0)// 光标处插入节点range.insertNode(node)// 取消insert node 后的选中状态,将光标恢复到 insert node 后面range.collapse(false)},// 输入框 焦点focus() {this.$refs.editor.focus()},// 插入图片insertImg() {this.$refs.EditorImage.show()},// 获取上传的图片路径imageSuccessCBK(arr) {arr.forEach(async res => {const oImage = await this.getImageObject(res, this.imgShowWidth, this.imgShowHeight)this.cursorInsert(oImage)this.changeDivText()})},/*** 删除所有标签属性,支持忽略标签* @param {*} str 字符串文本* @param {*} ignoreArr 要忽略的标签*/deleteTagAttr(str, tagArr) {if (typeof str !== 'string') returnconst reg = new RegExp(`<(?:(${tagArr.join('|')}))(.*?)(?:>|\/>)`, 'gi')return str.replace(reg, mstr => {return mstr.replace(/(<[A-z]+)(.*)?(\/?>)/gi, '$1$3')})},// 获取内容,需求需要html外层添加div标签,没要求直接获取this.$refs.editor.innerHTML即可changeDivText() {const html = this.$refs.editor.innerHTMLconst newHtml = html.substring(1, 4) === 'div' ? html : this.deleteTagAttr(this.$refs.editor.outerHTML, ['div'])this.$emit('input', newHtml)}}
}
</script><style lang="scss" scoped>
.contentAble{border-radius: 10px;border: 1px solid #dcdfe6;padding: 20px;min-height: 200px;word-break: break-all;overflow: hidden;position: relative;&:empty::before {content: attr(placeholder);color: #c0c4cf;}
}
.uploadImage{padding: 20px 20px 70px 20px
}
.insetImg{position: absolute;right: 30px;bottom: 30px;
}
</style>

使用例子:

import CanableText from '@/components/CanableText'
<CanableText v-model="content" placeholder="请输入内容" :uploadImage="true" />

显示结果:

使用contenteditable=“true“改造div可编辑文本框相关推荐

  1. div模拟textarea文本框,输入文字高度自适应,且实现字数统计和限制

    需求: 文本框可根据输入内容高度自适应,不带滚动条,高度可变的那种,我搜索了很多,发现textarea无法实现我的需求,scrollHeigh这个无法获取实际内容的高度(我用的是那种简单的,可能我写的 ...

  2. 仿淘宝图片空间 点击文字 出现可编辑文本框 提交ajax数据到后台修改

    思路来源:昨天看淘宝的图片空间,发现了一个效果. 点击宝贝的名字,出现一个可编辑的文本框,然后ajax提交(如果数据变的话),改变数据 看图说明: 编辑完了提交进行修改数据 自己做的代码效果如下: 具 ...

  3. gui设置可编辑文本框的回调函数_用Tkinter制作Python程序的图形用户界面(GUI),打包后比Qt5减少60M(77.5%)(实例63)...

    实例61使用PyQt5制作了图形用户界面(GUI).这个香是香,但是打包后的安装文件太大(约80M),感觉有些美中不足啊.由于这个GUI实在简单,从现实角度实在用不着高大上的PyQt5,所以改用Pyt ...

  4. pdf中如何编辑文本框

    在word中插入文本框对于经常接触文档的人来说可谓是信手拈来,但是在pdf文档中要进行这个操作该怎么办呢?方法也很简单! 第一步,先到网上下载一个捷速pdf编辑器: 下载好之后将编辑器打开,并单击左上 ...

  5. 【MATLAB】在MATLAB中利用GUI编写加法计算器,要求:通过两个编辑文本框实现两个数字的输入,点击“开始计算”按钮进行计算,并在用于结果显示的静态文本框中实现两输入数字的和的显示

    1)打开Matlab,点击工具栏上的[File]–>New–>GUI,命名为:addnum.fig  2)在addnum.fig面板里,拖曳3个静态文本TXT控件(不做任何修改).3个编辑 ...

  6. 富文本编辑器,可编辑div contentEditable=true,光标位置window.getSelection

    在近期项目中,需要在一个实时通信软件中,在发送消息时支持发送加粗的消息,现在总结一下使用心得. 需求: 在发送消息时,点击加粗图标,图标添加选中效果,输入的文字.添加的文字表情.@人员都需要显示为加粗 ...

  7. vue可编辑div_vue2 如何实现div contenteditable=“true”(类似于v-model)的效果

    发现问题 在 vue2 中对表单控件有着良好的双向数据绑定机制,但是对于要特定实现某些功能的输入时,我们就不得不使用到 contenteditable="true" 的 div , ...

  8. div模拟textarea文本域轻松实现高度自适应——张鑫旭

    by zhangxinxu from http://www.zhangxinxu.com 本文地址: http://www.zhangxinxu.com/wordpress/?p=1362 一.关于t ...

  9. contenteditable属性让div也可以当做输入框

    你知道div也可以当做输入框么? H5的全局属性contenteditable,带有contenteditable属性的div而不是input或者textarea来作为输入框(div可以根据内容自动调 ...

最新文章

  1. 《xUnit Test Patterns》学习笔记3 - Philosophy of Test Automation
  2. Java(三):序列化
  3. 做算法题时的一些小技巧
  4. [codevs 1743] 反转卡片
  5. android 使用AIDL实现进程间通讯
  6. JavaScript 如何打败众语言,成为 Node 的实现语言?
  7. 力扣题目——217. 存在重复元素
  8. plsql oracle client没有正确安装(plsql连接远程数据库)
  9. 求不规则立方体表面积java_不规则立方体体积计算
  10. PayPal支付配置
  11. html 转盘抽奖开发,html 大转盘抽奖
  12. CC2430基础——外部中断分析
  13. 软件测试非功能性需求,什么是非功能测试?非功能测试包括哪些类型?
  14. Linux HaProxy安装/启动/简单配置教程
  15. python--webdriver驱动浏览器操作(基础知识)
  16. Vue组件选项props
  17. 仿微信群聊头像(图像合成、缩放)
  18. (转载)深入分析HDFS原理及读写流程
  19. 【ubuntu】Ubuntu中Android NDK下载跟配置
  20. 校园快餐店网上订餐管理系统(JSP+MySQL+MyEclipse)

热门文章

  1. 虚拟直播硬核开启线上发布会未来可能性,XR直播技术加速品牌破圈
  2. C++程序翻译成C语言程序
  3. 超级计算机系统位数,为什么没有人开发128位系统
  4. WINCC 7.5 SP2
  5. Pandas模块:表计算与数据分析
  6. C语言变量随机时间,C语言随机数使用方法
  7. PDA和PAD的区别何在?
  8. 接口测试平台代码实现13:注册功能
  9. 减肥成功就靠六西格玛|优思学院
  10. flash剧本策划节约用水_节水活动剧本—节约用水人人有责